diff --git a/CMakeLists.txt b/CMakeLists.txt index d949c50..1c30e14 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ -cmake_minimum_required(VERSION 2.6 FATAL_ERROR) +cmake_minimum_required(VERSION 2.6 FATAL_ERROR) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") #set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR) @@ -6,7 +8,12 @@ file(COPY qcustomplot.h DESTINATION ${CMAKE_BINARY_DIR}) project(structrock) find_package(Qt4 REQUIRED) -find_package(PCL 1.6.0 REQUIRED) +find_package(PCL 1.6.0 REQUIRED) + +find_package(PostgreSQL REQUIRED) + +include_directories (${PostgreSQL_INCLUDE_DIRS}) +link_directories(${PostgreSQL_LIBRARY_DIRS}) if(${VTK_VERSION} VERSION_GREATER "6") find_package(VTK COMPONENTS @@ -41,9 +48,14 @@ set(myApp_ICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.icns) if(WIN32) set(GUI_TYPE WIN32) endif(WIN32) +if(APPLE) +set(GUI_TYPE MACOSX_BUNDLE) +set(MACOSX_BUNDLE_ICON_FILE icon.icns) +SET_SOURCE_FILES_PROPERTIES(${myApp_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") +endif(APPLE) ADD_EXECUTABLE(structrock ${GUI_TYPE} ${myApp_ICON} ${project_SOURCES} ${project_FORMS_HEADERS} ${project_HEADERS_MOC}) -TARGET_LINK_LIBRARIES(structrock ${QT_LIBRARIES} ${PCL_LIBRARIES} ${VTK_LIBRARIES}) +TARGET_LINK_LIBRARIES(structrock ${QT_LIBRARIES} ${PCL_LIBRARIES} ${VTK_LIBRARIES} ${PostgreSQL_LIBRARIES}) -#INSTALL(SCRIPT bundle.cmake) +#INSTALL(SCRIPT bundle.cmake) \ No newline at end of file diff --git a/FindPostgreSQL.cmake b/FindPostgreSQL.cmake new file mode 100644 index 0000000..5baf85e --- /dev/null +++ b/FindPostgreSQL.cmake @@ -0,0 +1,189 @@ +#.rst: +# FindPostgreSQL +# -------------- +# +# Find the PostgreSQL installation. +# +# This module defines +# +# :: +# +# PostgreSQL_LIBRARIES - the PostgreSQL libraries needed for linking +# PostgreSQL_INCLUDE_DIRS - the directories of the PostgreSQL headers +# PostgreSQL_LIBRARY_DIRS - the link directories for PostgreSQL libraries +# PostgreSQL_VERSION_STRING - the version of PostgreSQL found (since CMake 2.8.8) + +#============================================================================= +# Copyright 2004-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# ---------------------------------------------------------------------------- +# History: +# This module is derived from the module originally found in the VTK source tree. +# +# ---------------------------------------------------------------------------- +# Note: +# PostgreSQL_ADDITIONAL_VERSIONS is a variable that can be used to set the +# version mumber of the implementation of PostgreSQL. +# In Windows the default installation of PostgreSQL uses that as part of the path. +# E.g C:\Program Files\PostgreSQL\8.4. +# Currently, the following version numbers are known to this module: +# "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" +# +# To use this variable just do something like this: +# set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4") +# before calling find_package(PostgreSQL) in your CMakeLists.txt file. +# This will mean that the versions you set here will be found first in the order +# specified before the default ones are searched. +# +# ---------------------------------------------------------------------------- +# You may need to manually set: +# PostgreSQL_INCLUDE_DIR - the path to where the PostgreSQL include files are. +# PostgreSQL_LIBRARY_DIR - The path to where the PostgreSQL library files are. +# If FindPostgreSQL.cmake cannot find the include files or the library files. +# +# ---------------------------------------------------------------------------- +# The following variables are set if PostgreSQL is found: +# PostgreSQL_FOUND - Set to true when PostgreSQL is found. +# PostgreSQL_INCLUDE_DIRS - Include directories for PostgreSQL +# PostgreSQL_LIBRARY_DIRS - Link directories for PostgreSQL libraries +# PostgreSQL_LIBRARIES - The PostgreSQL libraries. +# +# ---------------------------------------------------------------------------- +# If you have installed PostgreSQL in a non-standard location. +# (Please note that in the following comments, it is assumed that +# points to the root directory of the include directory of PostgreSQL.) +# Then you have three options. +# 1) After CMake runs, set PostgreSQL_INCLUDE_DIR to /include and +# PostgreSQL_LIBRARY_DIR to wherever the library pq (or libpq in windows) is +# 2) Use CMAKE_INCLUDE_PATH to set a path to /PostgreSQL<-version>. This will allow find_path() +# to locate PostgreSQL_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g. In your CMakeLists.txt file +# set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "/include") +# 3) Set an environment variable called ${PostgreSQL_ROOT} that points to the root of where you have +# installed PostgreSQL, e.g. . +# +# ---------------------------------------------------------------------------- + +set(PostgreSQL_INCLUDE_PATH_DESCRIPTION "top-level directory containing the PostgreSQL include directories. E.g /usr/local/include/PostgreSQL/8.4 or C:/Program Files/PostgreSQL/8.4/include") +set(PostgreSQL_INCLUDE_DIR_MESSAGE "Set the PostgreSQL_INCLUDE_DIR cmake cache entry to the ${PostgreSQL_INCLUDE_PATH_DESCRIPTION}") +set(PostgreSQL_LIBRARY_PATH_DESCRIPTION "top-level directory containing the PostgreSQL libraries.") +set(PostgreSQL_LIBRARY_DIR_MESSAGE "Set the PostgreSQL_LIBRARY_DIR cmake cache entry to the ${PostgreSQL_LIBRARY_PATH_DESCRIPTION}") +set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to where PostgreSQL is found on the machine E.g C:/Program Files/PostgreSQL/8.4") + + +set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS} + "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") + +# Define additional search paths for root directories. +set( PostgreSQL_ROOT_DIRECTORIES + ENV PostgreSQL_ROOT + ${PostgreSQL_ROOT} +) +foreach(suffix ${PostgreSQL_KNOWN_VERSIONS}) + if(WIN32) + list(APPEND PostgreSQL_LIBRARY_ADDITIONAL_SEARCH_SUFFIXES + "PostgreSQL/${suffix}/lib") + list(APPEND PostgreSQL_INCLUDE_ADDITIONAL_SEARCH_SUFFIXES + "PostgreSQL/${suffix}/include") + list(APPEND PostgreSQL_TYPE_ADDITIONAL_SEARCH_SUFFIXES + "PostgreSQL/${suffix}/include/server") + endif() + if(UNIX) + list(APPEND PostgreSQL_TYPE_ADDITIONAL_SEARCH_SUFFIXES + "postgresql/${suffix}/server") + endif() +endforeach() + +# +# Look for an installation. +# +find_path(PostgreSQL_INCLUDE_DIR + NAMES libpq-fe.h + PATHS + # Look in other places. + ${PostgreSQL_ROOT_DIRECTORIES} + PATH_SUFFIXES + pgsql + postgresql + include + ${PostgreSQL_INCLUDE_ADDITIONAL_SEARCH_SUFFIXES} + # Help the user find it if we cannot. + DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}" +) + +find_path(PostgreSQL_TYPE_INCLUDE_DIR + NAMES catalog/pg_type.h + PATHS + # Look in other places. + ${PostgreSQL_ROOT_DIRECTORIES} + PATH_SUFFIXES + postgresql + pgsql/server + postgresql/server + include/server + ${PostgreSQL_TYPE_ADDITIONAL_SEARCH_SUFFIXES} + # Help the user find it if we cannot. + DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}" +) + +# The PostgreSQL library. +set (PostgreSQL_LIBRARY_TO_FIND pq) +# Setting some more prefixes for the library +set (PostgreSQL_LIB_PREFIX "") +if ( WIN32 ) + set (PostgreSQL_LIB_PREFIX ${PostgreSQL_LIB_PREFIX} "lib") + set (PostgreSQL_LIBRARY_TO_FIND ${PostgreSQL_LIB_PREFIX}${PostgreSQL_LIBRARY_TO_FIND}) +endif() + +find_library(PostgreSQL_LIBRARY + NAMES ${PostgreSQL_LIBRARY_TO_FIND} + PATHS + ${PostgreSQL_ROOT_DIRECTORIES} + PATH_SUFFIXES + lib + ${PostgreSQL_LIBRARY_ADDITIONAL_SEARCH_SUFFIXES} + # Help the user find it if we cannot. + DOC "The ${PostgreSQL_LIBRARY_DIR_MESSAGE}" +) +get_filename_component(PostgreSQL_LIBRARY_DIR ${PostgreSQL_LIBRARY} PATH) + +if (PostgreSQL_INCLUDE_DIR) + # Some platforms include multiple pg_config.hs for multi-lib configurations + # This is a temporary workaround. A better solution would be to compile + # a dummy c file and extract the value of the symbol. + file(GLOB _PG_CONFIG_HEADERS "${PostgreSQL_INCLUDE_DIR}/pg_config*.h") + foreach(_PG_CONFIG_HEADER ${_PG_CONFIG_HEADERS}) + if(EXISTS "${_PG_CONFIG_HEADER}") + file(STRINGS "${_PG_CONFIG_HEADER}" pgsql_version_str + REGEX "^#define[\t ]+PG_VERSION[\t ]+\".*\"") + if(pgsql_version_str) + string(REGEX REPLACE "^#define[\t ]+PG_VERSION[\t ]+\"([^\"]*)\".*" + "\\1" PostgreSQL_VERSION_STRING "${pgsql_version_str}") + break() + endif() + endif() + endforeach() + unset(pgsql_version_str) +endif() + +if (PostgreSQL_LIBRARY AND PostgreSQL_INCLUDE_DIR AND PostgreSQL_TYPE_INCLUDE_DIR) + set(PostgreSQL_FOUND TRUE) +endif() + +# Now try to get the include and library path. +if(PostgreSQL_FOUND) + set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} ) + set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} ) + set(PostgreSQL_LIBRARIES ${PostgreSQL_LIBRARY_TO_FIND}) +endif() + +mark_as_advanced(PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR PostgreSQL_LIBRARY ) \ No newline at end of file diff --git a/KinectV2Viewer.h b/KinectV2Viewer.h new file mode 100644 index 0000000..3ef8671 --- /dev/null +++ b/KinectV2Viewer.h @@ -0,0 +1,196 @@ +#ifndef KINECTV2VIEWER_H +#define KINECTV2VIEWER_H + +#include +#include +#include +#include + +using namespace pcl::io::openni2; + +template +class KinectV2Viewer +{ +public: + typedef pcl::PointCloud Cloud; + typedef typename Cloud::ConstPtr CloudConstPtr; + + KinectV2Viewer (pcl::Grabber* grabber, pcl::visualization::PCLVisualizer *cloud_viewer) + : cloud_viewer_ (cloud_viewer) + , image_viewer_ () + , depth_image_viewer_ () + , grabber_ (grabber) + , rgb_data_ (0), rgb_data_size_ (0) + { + } + + void + cloud_callback (const CloudConstPtr& cloud) + { + boost::mutex::scoped_lock lock (cloud_mutex_); + cloud_ = cloud; + } + + void + image_callback (const boost::shared_ptr& image) + { + boost::mutex::scoped_lock lock (image_mutex_); + image_ = image; + + if (image->getEncoding () != pcl::io::openni2::Image::RGB) + { + if (rgb_data_size_ < image->getWidth () * image->getHeight ()) + { + if (rgb_data_) + delete [] rgb_data_; + rgb_data_size_ = image->getWidth () * image->getHeight (); + rgb_data_ = new unsigned char [rgb_data_size_ * 3]; + } + image_->fillRGB (image_->getWidth (), image_->getHeight (), rgb_data_); + } + } + + void + depth_image_callback (const boost::shared_ptr& depth_image) + { + boost::mutex::scoped_lock lock (depth_image_mutex_); + depth_image_ = depth_image; + } + + /** + * @brief starts the main loop + */ + void + run () + { + cloud_viewer_->setCameraFieldOfView (1.02259994f); + boost::function cloud_cb = boost::bind (&KinectV2Viewer::cloud_callback, this, _1); + cloud_connection_ = grabber_->registerCallback (cloud_cb); + + if (grabber_->providesCallback&)>()) + { + image_viewer_ = new pcl::visualization::ImageViewer ("PCL OpenNI image"); + boost::function&) > image_cb = boost::bind (&KinectV2Viewer::image_callback, this, _1); + image_connection_ = grabber_->registerCallback (image_cb); + } + + depth_image_viewer_ = new pcl::visualization::ImageViewer ("Depth Image"); + boost::function&) > depth_image_cb = boost::bind (&KinectV2Viewer::depth_image_callback, this, _1); + depth_connection_ = grabber_->registerCallback (depth_image_cb); + + bool image_init = false, cloud_init = false, depth_image_init = false; + + grabber_->start (); + + while (grabber_->isRunning()) + { + boost::shared_ptr image; + boost::shared_ptr depth_image; + CloudConstPtr cloud; + + cloud_viewer_->spinOnce (); + + // See if we can get a cloud + if (cloud_mutex_.try_lock ()) + { + cloud_.swap (cloud); + cloud_mutex_.unlock (); + } + + if (cloud) + { + if (!cloud_init) + { + cloud_viewer_->setPosition (0, 0); + cloud_viewer_->setSize (cloud->width, cloud->height); + cloud_init = !cloud_init; + } + + if (!cloud_viewer_->updatePointCloud (cloud, "OpenNICloud")) + { + cloud_viewer_->addPointCloud (cloud, "OpenNICloud"); + cloud_viewer_->resetCameraViewpoint ("OpenNICloud"); + cloud_viewer_->setCameraPosition (0,0,0, // Position + 0,0,1, // Viewpoint + 0,-1,0); // Up + } + } + + // See if we can get an image + if (image_mutex_.try_lock ()) + { + image_.swap (image); + image_mutex_.unlock (); + } + + if (image) + { + if (!image_init && cloud && cloud->width != 0) + { + image_viewer_->setPosition (cloud->width, 0); + image_viewer_->setSize (image->getWidth (), image->getHeight ()); + image_init = !image_init; + } + + if (image->getEncoding () == pcl::io::openni2::Image::RGB) + image_viewer_->addRGBImage ( (const unsigned char*)image->getData (), image->getWidth (), image->getHeight ()); + else + image_viewer_->addRGBImage (rgb_data_, image->getWidth (), image->getHeight ()); + image_viewer_->spinOnce (); + } + + // See if we can get an ir image + if (depth_image_mutex_.try_lock ()) + { + depth_image_.swap (depth_image); + depth_image_mutex_.unlock (); + } + + if (depth_image) + { + if (!depth_image_init && cloud && cloud->width != 0) + { + depth_image_viewer_->setPosition (cloud->width, cloud->height); + depth_image_viewer_->setSize (depth_image->getWidth (), depth_image->getHeight ()); + depth_image_init = !depth_image_init; + } + + depth_image_viewer_->addShortImage(depth_image->getData (), depth_image->getWidth (), depth_image->getHeight (), true); + + depth_image_viewer_->spinOnce (); + } + } + + cloud_viewer_->removeAllPointClouds(); + cloud_viewer_->spinOnce (); + image_viewer_->close(); + depth_image_viewer_->close(); + + cloud_connection_.disconnect (); + image_connection_.disconnect (); + depth_connection_.disconnect (); + if (rgb_data_) + delete[] rgb_data_; + } + + pcl::visualization::PCLVisualizer *cloud_viewer_; + pcl::visualization::ImageViewer *image_viewer_; + pcl::visualization::ImageViewer *depth_image_viewer_; + + boost::signals2::connection cloud_connection_; + boost::signals2::connection image_connection_; + boost::signals2::connection depth_connection_; + + pcl::Grabber* grabber_; + boost::mutex cloud_mutex_; + boost::mutex image_mutex_; + boost::mutex depth_image_mutex_; + + CloudConstPtr cloud_; + boost::shared_ptr image_; + boost::shared_ptr depth_image_; + unsigned char* rgb_data_; + unsigned rgb_data_size_; +}; + +#endif // KINECTV2VIEWER_H \ No newline at end of file diff --git a/README.md b/README.md index a44ff5b..1c0b733 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,30 @@ # Structrock -A cross-platform outcrop point cloud processing system, -capable of acquiring fracture data on suppositional planes cutting through digital outcrop models (DOMs). +A cross-platform outcrop point cloud processing system. Structrock is released under the terms of the BSD license, and thus free for commercial and research use. Feel free to analyze your own outcrop point cloud data, to add Structrock into your own project. You are welcomed to make contributions to this project. Email ericrussell@zju.edu.cn, or open an issue here on GitHub for support. +Citation (more to be added soon): + +``` tex +@article{Wang_cageo2016, + title={A region-growing approach for automatic outcrop fracture extraction from a three-dimensional point cloud}, + author={Wang, Xin and Zou, Lejun and Shen, Xiaohua and Ren, Yupeng and Qin, Yi}, + journal={Computers \& Geosciences}, + year={2016}, + doi={10.1016/j.cageo.2016.11.002}, + publisher={Elsevier} +} +``` + +![Detailed results.](https://github.com/EricAlex/structrock/blob/master/wiki/img/detailed_results.jpg) +*Detailed results obtained from a portion of the point cloud. (a) A portion of the outcrop and (b) its point cloud. (c) Segmentation results obtained using the proposed algorithm. Different fracture regions are shown in various colors, and the non-fracture regions are shown in red. (d) Estimated fracture planes obtained from the segmentation results.* + +![Outcrop results.](https://github.com/EricAlex/structrock/blob/master/wiki/img/outcrop_results.jpg) +*(a) The outcrop used to test the proposed algorithm and (b) the segmentation results. Different fracture regions are shown by different colors, and the non-fracture regions are shown in red.* + ## Dependencies ### Point Cloud Library (PCL) @@ -22,18 +40,31 @@ Qt is a cross-platform C++ application development framework. Official website: Version required: >= 4.8. +### PostgreSQL + +PostgreSQL often simply Postgres, +is an object-relational database management system (ORDBMS) with an emphasis on extensibility and standards-compliance. +It is used to support an experimental function of structrock: accessing very large LiDAR datasets stored in PostgreSQL databases. + ## Functions -Structrock provide a platform on which workflows of processing outcrop point clouds can be designed. -A special algorithm to identify and segment fracture faces is implemented. -Algorithm of restoring a suppositional plane cutting through digital outcrop models (DOMs) is implemented. -Fracture data are acquired from DOMs and displayed. +Structrock provide a platform on which workflows of processing outcrop point clouds can be designed. A region-growing algorithm for automatic outcrop fracture extraction from a three-dimensional point cloud is implemented. Structrock can run in both GUI and command-line modes. In GUI mode, users interact with Structrock to perform certain processing action and provide processing parameters through input dialogs. -In command-line mode, Structrock receive the path to a text file that contains processing action and parameters, separated with ";". +In command-line mode, Structrock receive the path to a text file (we call it the workflow file) that contains processing actions and parameters. Lines of actions are separated by ";" and parameters are separated by ",". It will do these processing actions one by one until the end or errors occur. +An example of workflow file: + +``` txt +openpcd,E:\Downloads\parameters_test\0134067-Data-ready.pcd,mute; +knnormal,30,mute; +rgsegmentation,9,0.06,20,4,30,false,mute; +saveclusters,E:\Downloads\parameters_test\Clusters\Data_9_20.bin,mute; +quitsession; +``` + ## Build from source First, all dependencies, PCL(1.6), Qt, boost, Eigen, FLANN, VTK, QHull and OpenNI should be installed properly. @@ -52,4 +83,182 @@ add "/ENTRY:mainCRTStartup" to "structrock"'s "Linker->Command Line" properties, ### On Linux -Open terminal window, go to "build" folder, run "cmake ../src", then run "make". \ No newline at end of file +Open terminal window, go to "build" folder, run "cmake ../src", then run "make". + +### After a successful compilation, Structrock looks like this: + +![GUI.](https://github.com/EricAlex/structrock/blob/master/wiki/img/gui.jpg) + +## Processing actions + +### openpcd + +Description: Open a .pcd file. + +Parameters: + +1. "The path and file name of the file to open" (required), + +2. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +3. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### openxyz + +Description: Open a .txt file that contains 3 columns: x, y, z. + +Parameters: + +1. "The path and file name of the file to open" (required), + +2. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +3. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### savepcdascii + +Description: Save current data to .pcd file with ASCII encoding. + +Parameters: + +1. "The path and file name of the file to save" (required) + +### savepcdbinary + +Description: Save current data to .pcd file with binary encoding. + +Parameters: + +1. "The path and file name of the file to save" (required) + +### savenormals + +Description: Save current normals to .pcd file. + +Parameters: + +1. "The path and file name of the file to save" (required) + +### saveclusters + +Description: Perform post-outcrop-fracture-extraction actions and save the results into .bin and txt files. + +Parameters: + +1. "The path and file name of the file to save" (required), + +2. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +3. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### downsample + +Description: downsample the point cloud given the minimum point distance (meter). + +Parameters: + +1. "Minimum point distance" (required, double), + +2. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +3. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### resample + +Description: resample the point cloud given the search radius (meter). + +Parameters: + +1. "Search radius" (required, double), + +2. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +3. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### knnormal + +Description: find k nearest neighbors given k, and calculate the normal of the neighbors. + +Parameters: + +1. "Number of neoghbor points" (required, int), + +2. showcurvature (optional, follow required parameters, but before "mute" and "nolog", if declared, the curvature map on the point cloud will be displayed on the screen), + +3. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +4. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### ranormal + +Description: find the neighbors given the search radius, and calculate the normal of the neighbors. + +Parameters: + +1. "Search radius" (required, double), + +2. showcurvature (optional, follow required parameters, but before "mute" and "nolog", if declared, the curvature map on the point cloud will be displayed on the screen), + +3. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +4. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### rostatic + +Description: statistically remove the outliers of the point cloud given the standard deviation. + +Parameters: + +1. "Standard deviation" (required, double), + +2. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +3. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### rgsegmentation + +Description: perform the Region Growing Segmentation given the parameters. + +Parameters: + +1. "Local surface normal deviation threshold" (required, double, degree), + +2. "Curvature threshold" (required, double, only used when the smooth mode is on), + +3. "Transmission error threshold" (required, double, degree, only used when the smooth mode is off), + +4. "Minimum number of point a segmented patch must have to be recorded" (required, int), + +5. "The number of neighbors will participate in the region growing" (required, int), + +6. "Is it on smooth mode?" (required, boolean), + +7. mute (optional, follow required parameters, if declared, the result of this action will not be displayed on the screen), + +8. nolog (optional, follow required parameters, if declared, this action and the time it takes to perform this action will not be logged) + +### showsfeature + +Description: Show different kinds of features on the fracture faces or on the outcrop. Features include the fracture faces' roughness, area, linear features, circular features, wave-like features, and etc. + +Parameters: + +1. "The name of the feature" (required, currently "roughness" and "area" are included.) + +2. "Percentage Out threshold" (Optional; Less than 0.5 and bigger than 0.0. If provided, drop the head and the tail in the distribution of the feature to show the variation of the majority of the feature data.) + +### quitsession + +Description: quit Structrock. + +Parameters: + +No parameters. + +### showstereonet + +Description: Show and save (as PDF) the stereonet plot of the fracture data. + +Parameters: + +1. "The path and file name of the file to save" (required) \ No newline at end of file diff --git a/RGSWorker.cpp b/RGSWorker.cpp index 319ccf8..e83435e 100755 --- a/RGSWorker.cpp +++ b/RGSWorker.cpp @@ -37,6 +37,9 @@ * */ +#include +#include +#include #include #include #include "RGSWorker.h" @@ -53,6 +56,9 @@ void RGSWorker::doWork() dataLibrary::Status = STATUS_RGS; + dataLibrary::start = clock(); + + //begin of processing double curvature = dataLibrary::RGSparameter.curvature; double smoothness = dataLibrary::RGSparameter.smoothness; double residual = dataLibrary::RGSparameter.residual; @@ -83,8 +89,25 @@ void RGSWorker::doWork() dataLibrary::cloudxyzrgb_clusters = reg.getColoredCloud(); - emit show(); is_success = true; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tRegion Growing Segmentation costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(); + } + dataLibrary::Status = STATUS_READY; emit showReadyStatus(); if(this->getWorkFlowMode()&&is_success) @@ -92,4 +115,4 @@ void RGSWorker::doWork() this->Sleep(1000); emit GoWorkFlow(); } -} +} \ No newline at end of file diff --git a/ReadFileWorker.cpp b/ReadFileWorker.cpp index 0000557..89a23c6 100755 --- a/ReadFileWorker.cpp +++ b/ReadFileWorker.cpp @@ -37,9 +37,14 @@ * */ +#include +#include +#include #include #include #include +#include +#include #include "ReadFileWorker.h" #include "globaldef.h" #include "dataLibrary.h" @@ -52,43 +57,63 @@ void ReadFileWorker::doWork(const QString &filename) QByteArray ba = filename.toLocal8Bit(); std::string* strfilename = new std::string(ba.data()); - sensor_msgs::PointCloud2::Ptr cloud_blob(new sensor_msgs::PointCloud2); + pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2); dataLibrary::Status = STATUS_OPENPCD; + dataLibrary::start = clock(); + + //begin of processing if(!pcl::io::loadPCDFile (*strfilename, *cloud_blob)) { dataLibrary::clearall(); - pcl::fromROSMsg (*cloud_blob, *dataLibrary::cloudxyz); + pcl::fromPCLPointCloud2 (*cloud_blob, *dataLibrary::cloudxyz); if(pcl::getFieldIndex (*cloud_blob, "rgb")<0) { dataLibrary::cloudID = *strfilename; - - emit ReadFileReady(CLOUDXYZ); + if(!this->getMuteMode()) + { + emit ReadFileReady(CLOUDXYZ); + } is_success = true; } else { - pcl::fromROSMsg (*cloud_blob, *dataLibrary::cloudxyzrgb); + pcl::fromPCLPointCloud2 (*cloud_blob, *dataLibrary::cloudxyzrgb); dataLibrary::cloudID = *strfilename; - - emit ReadFileReady(CLOUDXYZRGB); + if(!this->getMuteMode()) + { + emit ReadFileReady(CLOUDXYZRGB); + } is_success = true; } - delete strfilename; - if(this->getWorkFlowMode()&&is_success) - { - this->Sleep(1000); - emit GoWorkFlow(); - } } else { emit showErrors("Error opening pcd file."); } + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMode()&&is_success) + { + std::string string_filename = filename.toUtf8().constData(); + std::string log_text = string_filename + "\n\tReading PCD file costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish - dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() + " seconds."); + dataLibrary::write_text_to_log_file(log_text); + } dataLibrary::Status = STATUS_READY; emit showReadyStatus(); + delete strfilename; + if(this->getWorkFlowMode()&&is_success) + { + this->Sleep(1000); + emit GoWorkFlow(); + } } \ No newline at end of file diff --git a/ReadXYZWorker.cpp b/ReadXYZWorker.cpp index c10490d..4628829 100755 --- a/ReadXYZWorker.cpp +++ b/ReadXYZWorker.cpp @@ -39,6 +39,8 @@ #include #include +#include +#include #include #include "ReadXYZWorker.h" #include "globaldef.h" @@ -69,7 +71,7 @@ bool loadCloud (const string &filename, pcl::PointCloud &cloud) // Tokenize the line boost::trim (line); - boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on); + boost::split (st, line, boost::is_any_of (",\t\r "), boost::token_compress_on); if (st.size () < 3) continue; @@ -93,9 +95,15 @@ void ReadXYZWorker::doWork(const QString &filename) dataLibrary::Status = STATUS_OPENXYZ; - if(loadCloud (*strfilename, *dataLibrary::cloudxyz)) + dataLibrary::start = clock(); + + //begin of processing + if(loadCloud (*strfilename, *dataLibrary::cloudxyz)) { - emit ReadXYZReady(CLOUDXYZ); + if(!this->getMuteMode()) + { + emit ReadXYZReady(CLOUDXYZ); + } is_success = true; } else @@ -104,6 +112,19 @@ void ReadXYZWorker::doWork(const QString &filename) } dataLibrary::cloudID = *strfilename; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMode()&&is_success) + { + std::string string_filename = filename.toUtf8().constData(); + std::string log_text = string_filename + "\n\tReading XYZ file costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish - dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() + " seconds."); + dataLibrary::write_text_to_log_file(log_text); + } dataLibrary::Status = STATUS_READY; emit showReadyStatus(); diff --git a/SaveClustersWorker.cpp b/SaveClustersWorker.cpp index 8e30348..2f1372e 100755 --- a/SaveClustersWorker.cpp +++ b/SaveClustersWorker.cpp @@ -37,6 +37,8 @@ * */ +#include +#include #include #include #include @@ -73,7 +75,10 @@ void SaveClustersWorker::doWork(const QString &filename) string* strfilename = new string(ba.data()); dataLibrary::Status = STATUS_SAVECLUSTERS; + + dataLibrary::start = clock(); + //begin of processing //compute centor point and normal float nx_all, ny_all, nz_all; float curvature_all; @@ -156,12 +161,16 @@ void SaveClustersWorker::doWork(const QString &filename) string textfilename = strfilename->substr(0, strfilename->size()-4) += "_table.txt"; string dip_dipdir_file = strfilename->substr(0, strfilename->size()-4) += "_dip_dipdir.txt"; string dipdir_dip_file = strfilename->substr(0, strfilename->size()-4) += "_dipdir_dip.txt"; + string area_file = strfilename->substr(0, strfilename->size()-4) += "_area.txt"; + string roughness_file = strfilename->substr(0, strfilename->size()-4) += "_roughness.txt"; string fracture_intensity = strfilename->substr(0, strfilename->size()-4) += "_fracture_intensity.txt"; ofstream fout(textfilename.c_str()); ofstream dip_dipdir_out(dip_dipdir_file.c_str()); ofstream dipdir_dip_out(dipdir_dip_file.c_str()); + ofstream area_out(area_file.c_str()); + ofstream roughness_out(roughness_file.c_str()); ofstream fracture_intensity_out(fracture_intensity.c_str()); - fout<<"Flag"<<"\t"<<"Number"<<"\t"<<"Points"<<"\t"<<"Direc"<<"\t"<<"Dip"<<"\t"<<"Area"<<"\t"<<"Length"<<"\n"; + fout<<"Flag"<<"\t"<<"Number"<<"\t"<<"Points"<<"\t"<<"Direc"<<"\t"<<"Dip"<<"\t"<<"Area"<<"\t"<<"Length"<<"\t"<<"Roughness"<<"\n"; int num_of_clusters = dataLibrary::clusters.size(); ofstream fbinaryout(strfilename->c_str(), std::ios::out|std::ios::binary|std::ios::app); @@ -275,9 +284,25 @@ void SaveClustersWorker::doWork(const QString &filename) dip = 90.0 - atan(fabs(nz)/sqrt((nx*nx + ny*ny)))*180/M_PI; } + //calculate fracture surface roughness + float fracture_total_distance=0.0; + for(int j = 0; j < plane_cloud->size(); j++) + { + Eigen::Vector3f Q; + Q(0)=plane_cloud->at(j).x; + Q(1)=plane_cloud->at(j).y; + Q(2)=plane_cloud->at(j).z; + fracture_total_distance+=std::abs((Q-centroid).dot(normal)/std::sqrt((normal.dot(normal)))); + } + float fracture_roughness=fracture_total_distance/plane_cloud->size(); + + //saved for further analysis + dataLibrary::areas.push_back(area); + dataLibrary::roughnesses.push_back(fracture_roughness); + float length; bool flag = dataLibrary::CheckClusters(dataLibrary::plane_normal_all, centroid_all, dataLibrary::cloud_hull_all, normal, centroid, cloud_projected, cluster_index, length, false); - fout<getWriteLogMode()&&is_success) + { + std::string log_text = "\tSaving Clusters costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish - dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() + " seconds."); + dataLibrary::write_text_to_log_file(log_text); + } - emit SaveClustersReady(filename); - is_success = true; + if(!this->getMuteMode()&&is_success) + { + emit SaveClustersReady(filename); + } + dataLibrary::Status = STATUS_READY; emit showReadyStatus(); - delete strfilename; if(this->getWorkFlowMode()&&is_success) { diff --git a/SaveNormalsWorker.cpp b/SaveNormalsWorker.cpp index 9d45a63..c9570f8 100755 --- a/SaveNormalsWorker.cpp +++ b/SaveNormalsWorker.cpp @@ -47,38 +47,35 @@ void SaveNormalsWorker::doWork(const QString &filename) { bool is_success(false); - if(!filename.isNull()) - { - dataLibrary::Status = STATUS_SAVENORMALS; + QByteArray ba = filename.toLocal8Bit(); + std::string* strfilename = new std::string(ba.data()); + + dataLibrary::Status = STATUS_SAVENORMALS; - QByteArray ba = filename.toLocal8Bit(); - std::string* strfilename = new std::string(ba.data()); - if(dataLibrary::pointnormals->empty()) + //begin of processing + if(dataLibrary::pointnormals->empty()) + { + emit showErrors(QString("You Haven't Extracted Any Normals Yet!")); + } + else + { + if(!pcl::io::savePCDFileBinary(*strfilename, *dataLibrary::pointnormals)) { - emit showErrors(QString("You Haven't Extracted Any Normals Yet!")); + is_success = true; } else { - if(!pcl::io::savePCDFileBinary(*strfilename, *dataLibrary::pointnormals)) - { - is_success = true; - } - else - { - emit showErrors("Saving normals failed."); - } - } - delete strfilename; - dataLibrary::Status = STATUS_READY; - emit showReadyStatus(); - if(this->getWorkFlowMode()&&is_success) - { - this->Sleep(1000); - emit GoWorkFlow(); + emit showErrors("Saving normals failed."); } } - else + //end of processing + + delete strfilename; + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); + if(this->getWorkFlowMode()&&is_success) { - emit showErrors("Empty file name."); + this->Sleep(1000); + emit GoWorkFlow(); } } \ No newline at end of file diff --git a/SavePcdASCIIWorker.cpp b/SavePcdASCIIWorker.cpp index d4f131f..7007ab8 100755 --- a/SavePcdASCIIWorker.cpp +++ b/SavePcdASCIIWorker.cpp @@ -47,52 +47,48 @@ void SavePcdASCIIWorker::doWork(const QString &filename) { bool is_success(false); - if(!filename.isNull()) - { - dataLibrary::Status = STATUS_SAVEASCII; + dataLibrary::checkupflow(); + + QByteArray ba = filename.toLocal8Bit(); + std::string* strfilename = new std::string(ba.data()); - QByteArray ba = filename.toLocal8Bit(); - std::string* strfilename = new std::string(ba.data()); + dataLibrary::Status = STATUS_SAVEASCII; - if(dataLibrary::cloudxyz->empty()&&dataLibrary::cloudxyzrgb->empty()) + //begin of processing + if(dataLibrary::cloudxyz->empty()&&dataLibrary::cloudxyzrgb->empty()) + { + emit showErrors(QString("You Haven't Opened Any Dataset Yet!")); + } + else if(!dataLibrary::cloudxyz->empty()) + { + if(!pcl::io::savePCDFileASCII(*strfilename, *dataLibrary::cloudxyz)) { - emit showErrors(QString("You Haven't Opened Any Dataset Yet!")); + is_success = true; } - else if(!dataLibrary::cloudxyz->empty()) + else { - dataLibrary::checkupflow(); - - if(!pcl::io::savePCDFileASCII(*strfilename, *dataLibrary::cloudxyz)) - { - is_success = true; - } - else - { - emit showErrors("Saving pcd as ASCII failed."); - } + emit showErrors("Saving pcd as ASCII failed."); } - else if(!dataLibrary::cloudxyzrgb->empty()) + } + else if(!dataLibrary::cloudxyzrgb->empty()) + { + if(!pcl::io::savePCDFileASCII(*strfilename, *dataLibrary::cloudxyzrgb)) { - if(!pcl::io::savePCDFileASCII(*strfilename, *dataLibrary::cloudxyzrgb)) - { - is_success = true; - } - else - { - emit showErrors("Saving pcd as ASCII failed."); - } + is_success = true; } - delete strfilename; - dataLibrary::Status = STATUS_READY; - emit showReadyStatus(); - if(this->getWorkFlowMode()&&is_success) + else { - this->Sleep(1000); - emit GoWorkFlow(); + emit showErrors("Saving pcd as ASCII failed."); } } - else + //end of processing + + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); + delete strfilename; + if(this->getWorkFlowMode()&&is_success) { - emit showErrors("Empty file name."); + this->Sleep(1000); + emit GoWorkFlow(); } } \ No newline at end of file diff --git a/SavePcdBinaryWorker.cpp b/SavePcdBinaryWorker.cpp index 8ac4c59..7928d67 100755 --- a/SavePcdBinaryWorker.cpp +++ b/SavePcdBinaryWorker.cpp @@ -47,51 +47,48 @@ void SavePcdBinaryWorker::doWork(const QString &filename) { bool is_success(false); - if(!filename.isNull()) - { - dataLibrary::Status = STATUS_SAVEBINARY; + dataLibrary::checkupflow(); + + QByteArray ba = filename.toLocal8Bit(); + std::string* strfilename = new std::string(ba.data()); - QByteArray ba = filename.toLocal8Bit(); - std::string* strfilename = new std::string(ba.data()); + dataLibrary::Status = STATUS_SAVEBINARY; - if(dataLibrary::cloudxyz->empty()&&dataLibrary::cloudxyzrgb->empty()) + //begin of processing + if(dataLibrary::cloudxyz->empty()&&dataLibrary::cloudxyzrgb->empty()) + { + emit showErrors(QString("You Haven't Opened Any Dataset Yet!")); + } + else if(!dataLibrary::cloudxyz->empty()) + { + if(!pcl::io::savePCDFileBinary(*strfilename, *dataLibrary::cloudxyz)) { - emit showErrors(QString("You Haven't Opened Any Dataset Yet!")); + is_success = true; } - else if(!dataLibrary::cloudxyz->empty()) + else { - dataLibrary::checkupflow(); - if(!pcl::io::savePCDFileBinary(*strfilename, *dataLibrary::cloudxyz)) - { - is_success = true; - } - else - { - emit showErrors("Saving pcd as binary failed."); - } + emit showErrors("Saving pcd as binary failed."); } - else if(!dataLibrary::cloudxyzrgb->empty()) + } + else if(!dataLibrary::cloudxyzrgb->empty()) + { + if(!pcl::io::savePCDFileBinary(*strfilename, *dataLibrary::cloudxyzrgb)) { - if(!pcl::io::savePCDFileBinary(*strfilename, *dataLibrary::cloudxyzrgb)) - { - is_success = true; - } - else - { - emit showErrors("Saving pcd as binary failed."); - } + is_success = true; } - delete strfilename; - dataLibrary::Status = STATUS_READY; - emit showReadyStatus(); - if(this->getWorkFlowMode()&&is_success) + else { - this->Sleep(1000); - emit GoWorkFlow(); + emit showErrors("Saving pcd as binary failed."); } } - else + //end of processing + + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); + delete strfilename; + if(this->getWorkFlowMode()&&is_success) { - emit showErrors("Empty file name."); + this->Sleep(1000); + emit GoWorkFlow(); } } \ No newline at end of file diff --git a/ShowProcessWorker.cpp b/ShowProcessWorker.cpp index f336be6..b69c473 100755 --- a/ShowProcessWorker.cpp +++ b/ShowProcessWorker.cpp @@ -67,173 +67,191 @@ void ShowProcessWorker::doWork() { bool is_success(false); - if(dataLibrary::clusters.size() == 0) + dataLibrary::Status = STATUS_SHOWPROCESS; + + dataLibrary::start = clock(); + + //begin of processing + //Clear data if needed + if(!dataLibrary::cloud_hull_all->empty()) + dataLibrary::cloud_hull_all->clear(); + if(dataLibrary::fracture_faces_hull.size()!=0) + std::vector::Ptr>().swap(dataLibrary::fracture_faces_hull); + if(dataLibrary::Lines.size()!=0) + std::vector().swap(dataLibrary::Lines); + if(dataLibrary::Lines_max.size()!=0) + std::vector().swap(dataLibrary::Lines_max); + if(dataLibrary::Lines_min.size()!=0) + std::vector().swap(dataLibrary::Lines_min); + if(!dataLibrary::segmentation_rem->empty()) + dataLibrary::segmentation_rem->clear(); + + //compute centor point and normal + float nx_all, ny_all, nz_all; + float curvature_all; + Eigen::Matrix3f convariance_matrix_all; + Eigen::Vector4f xyz_centroid_all, plane_parameters_all; + pcl::compute3DCentroid(*dataLibrary::cloudxyz, xyz_centroid_all); + pcl::computeCovarianceMatrix(*dataLibrary::cloudxyz, xyz_centroid_all, convariance_matrix_all); + pcl::solvePlaneParameters(convariance_matrix_all, nx_all, ny_all, nz_all, curvature_all); + Eigen::Vector3f centroid_all; + dataLibrary::plane_normal_all(0)=nx_all; + dataLibrary::plane_normal_all(1)=ny_all; + dataLibrary::plane_normal_all(2)=nz_all; + centroid_all(0)=xyz_centroid_all(0); + centroid_all(1)=xyz_centroid_all(1); + centroid_all(2)=xyz_centroid_all(2); + + if(dataLibrary::checkContents(dataLibrary::contents, "suppositional_plane")) { - emit showErrors("ShowProcess: You Haven't Performed Any Segmentation Yet!"); + //project all points + pcl::ModelCoefficients::Ptr coefficients_all (new pcl::ModelCoefficients()); + coefficients_all->values.resize(4); + coefficients_all->values[0] = nx_all; + coefficients_all->values[1] = ny_all; + coefficients_all->values[2] = nz_all; + coefficients_all->values[3] = - (nx_all*xyz_centroid_all[0] + ny_all*xyz_centroid_all[1] + nz_all*xyz_centroid_all[2]); + + pcl::PointCloud::Ptr cloud_projected_all (new pcl::PointCloud); + pcl::ProjectInliers proj_all; + proj_all.setModelType(pcl::SACMODEL_PLANE); + proj_all.setInputCloud(dataLibrary::cloudxyz); + proj_all.setModelCoefficients(coefficients_all); + proj_all.filter(*cloud_projected_all); + + //compute convex hull + pcl::ConvexHull chull_all; + chull_all.setInputCloud(cloud_projected_all); + chull_all.reconstruct(*dataLibrary::cloud_hull_all); } - else + + if(dataLibrary::checkContents(dataLibrary::contents, "fracture_faces")) { - dataLibrary::Status = STATUS_SHOWPROCESS; - - //Clear data if needed - if(!dataLibrary::cloud_hull_all->empty()) - dataLibrary::cloud_hull_all->clear(); - if(dataLibrary::fracture_faces_hull.size()!=0) - std::vector::Ptr>().swap(dataLibrary::fracture_faces_hull); - if(dataLibrary::Lines.size()!=0) - std::vector().swap(dataLibrary::Lines); - if(dataLibrary::Lines_max.size()!=0) - std::vector().swap(dataLibrary::Lines_max); - if(dataLibrary::Lines_min.size()!=0) - std::vector().swap(dataLibrary::Lines_min); - if(!dataLibrary::segmentation_rem->empty()) - dataLibrary::segmentation_rem->clear(); - - //compute centor point and normal - float nx_all, ny_all, nz_all; - float curvature_all; - Eigen::Matrix3f convariance_matrix_all; - Eigen::Vector4f xyz_centroid_all, plane_parameters_all; - pcl::compute3DCentroid(*dataLibrary::cloudxyz, xyz_centroid_all); - pcl::computeCovarianceMatrix(*dataLibrary::cloudxyz, xyz_centroid_all, convariance_matrix_all); - pcl::solvePlaneParameters(convariance_matrix_all, nx_all, ny_all, nz_all, curvature_all); - Eigen::Vector3f centroid_all; - dataLibrary::plane_normal_all(0)=nx_all; - dataLibrary::plane_normal_all(1)=ny_all; - dataLibrary::plane_normal_all(2)=nz_all; - centroid_all(0)=xyz_centroid_all(0); - centroid_all(1)=xyz_centroid_all(1); - centroid_all(2)=xyz_centroid_all(2); - - if(dataLibrary::checkContents(dataLibrary::contents, "suppositional_plane")) + bool show_rem = false; + pcl::PointIndices::Ptr indices_all(new pcl::PointIndices); + indices_all->header=dataLibrary::clusters[0].header; + if(dataLibrary::checkContents(dataLibrary::contents, "rgs_remanent")) + { + show_rem = true; + } + bool show_fracture_traces = false; + bool show_extension_line = false; + if(dataLibrary::checkContents(dataLibrary::contents, "suppositional_plane")&&dataLibrary::checkContents(dataLibrary::contents, "fracture_traces")) { - //project all points - pcl::ModelCoefficients::Ptr coefficients_all (new pcl::ModelCoefficients()); - coefficients_all->values.resize(4); - coefficients_all->values[0] = nx_all; - coefficients_all->values[1] = ny_all; - coefficients_all->values[2] = nz_all; - coefficients_all->values[3] = - (nx_all*xyz_centroid_all[0] + ny_all*xyz_centroid_all[1] + nz_all*xyz_centroid_all[2]); - - pcl::PointCloud::Ptr cloud_projected_all (new pcl::PointCloud); - pcl::ProjectInliers proj_all; - proj_all.setModelType(pcl::SACMODEL_PLANE); - proj_all.setInputCloud(dataLibrary::cloudxyz); - proj_all.setModelCoefficients(coefficients_all); - proj_all.filter(*cloud_projected_all); - - //compute convex hull - pcl::ConvexHull chull_all; - chull_all.setInputCloud(cloud_projected_all); - chull_all.reconstruct(*dataLibrary::cloud_hull_all); + show_fracture_traces = true; + } + if(dataLibrary::checkContents(dataLibrary::contents, "suppositional_plane")&&dataLibrary::checkContents(dataLibrary::contents, "extension_line")) + { + show_extension_line = true; } - if(dataLibrary::checkContents(dataLibrary::contents, "fracture_faces")) + for(int cluster_index = 0; cluster_index < dataLibrary::clusters.size(); cluster_index++) { - bool show_rem = false; - pcl::PointIndices::Ptr indices_all(new pcl::PointIndices); - indices_all->header=dataLibrary::clusters[0].header; - if(dataLibrary::checkContents(dataLibrary::contents, "rgs_remanent")) + //Add colored patch polygons + pcl::PointCloud::Ptr plane_cloud (new pcl::PointCloud); + for(int j = 0; j < dataLibrary::clusters[cluster_index].indices.size(); j++) { - show_rem = true; + plane_cloud->push_back(dataLibrary::cloudxyz->at(dataLibrary::clusters[cluster_index].indices[j])); } - bool show_fracture_traces = false; - bool show_extension_line = false; - if(dataLibrary::checkContents(dataLibrary::contents, "suppositional_plane")&&dataLibrary::checkContents(dataLibrary::contents, "fracture_traces")) - { - show_fracture_traces = true; - } - if(dataLibrary::checkContents(dataLibrary::contents, "suppositional_plane")&&dataLibrary::checkContents(dataLibrary::contents, "extension_line")) + + //prepare for projecting data onto plane + float nx, ny, nz; + float curvature; + Eigen::Matrix3f convariance_matrix; + Eigen::Vector4f xyz_centroid, plane_parameters; + pcl::compute3DCentroid(*plane_cloud, xyz_centroid); + pcl::computeCovarianceMatrix(*plane_cloud, xyz_centroid, convariance_matrix); + pcl::solvePlaneParameters(convariance_matrix, nx, ny, nz, curvature); + Eigen::Vector3f centroid; + centroid(0)=xyz_centroid(0); + centroid(1)=xyz_centroid(1); + centroid(2)=xyz_centroid(2); + + //project data onto plane + //set plane parameter + pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients()); + coefficients->values.resize(4); + coefficients->values[0] = nx; + coefficients->values[1] = ny; + coefficients->values[2] = nz; + coefficients->values[3] = - (nx*xyz_centroid[0] + ny*xyz_centroid[1] + nz*xyz_centroid[2]); + //projecting + pcl::PointCloud::Ptr cloud_projected (new pcl::PointCloud); + pcl::ProjectInliers proj; + proj.setModelType(pcl::SACMODEL_PLANE); + proj.setInputCloud(plane_cloud); + proj.setModelCoefficients(coefficients); + proj.filter(*cloud_projected); + + //generate a convex hull + pcl::PointCloud::Ptr cloud_hull (new pcl::PointCloud); + pcl::ConvexHull chull; + chull.setInputCloud(cloud_projected); + chull.reconstruct(*cloud_hull); + dataLibrary::fracture_faces_hull.push_back(cloud_hull); + + if(show_rem) { - show_extension_line = true; + indices_all->indices.insert(indices_all->indices.end(), dataLibrary::clusters[cluster_index].indices.begin(), dataLibrary::clusters[cluster_index].indices.end()); } - for(int cluster_index = 0; cluster_index < dataLibrary::clusters.size(); cluster_index++) + Eigen::Vector3f normal; + normal(0) = nx; + normal(1) = ny; + normal(2) = nz; + + if(show_fracture_traces) { - //Add colored patch polygons - pcl::PointCloud::Ptr plane_cloud (new pcl::PointCloud); - for(int j = 0; j < dataLibrary::clusters[cluster_index].indices.size(); j++) + float length; + if(show_extension_line) { - plane_cloud->push_back(dataLibrary::cloudxyz->at(dataLibrary::clusters[cluster_index].indices[j])); + bool flag = dataLibrary::CheckClusters(dataLibrary::plane_normal_all, centroid_all, dataLibrary::cloud_hull_all, normal, centroid, cloud_projected, cluster_index, length, true); } - - //prepare for projecting data onto plane - float nx, ny, nz; - float curvature; - Eigen::Matrix3f convariance_matrix; - Eigen::Vector4f xyz_centroid, plane_parameters; - pcl::compute3DCentroid(*plane_cloud, xyz_centroid); - pcl::computeCovarianceMatrix(*plane_cloud, xyz_centroid, convariance_matrix); - pcl::solvePlaneParameters(convariance_matrix, nx, ny, nz, curvature); - Eigen::Vector3f centroid; - centroid(0)=xyz_centroid(0); - centroid(1)=xyz_centroid(1); - centroid(2)=xyz_centroid(2); - - //project data onto plane - //set plane parameter - pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients()); - coefficients->values.resize(4); - coefficients->values[0] = nx; - coefficients->values[1] = ny; - coefficients->values[2] = nz; - coefficients->values[3] = - (nx*xyz_centroid[0] + ny*xyz_centroid[1] + nz*xyz_centroid[2]); - //projecting - pcl::PointCloud::Ptr cloud_projected (new pcl::PointCloud); - pcl::ProjectInliers proj; - proj.setModelType(pcl::SACMODEL_PLANE); - proj.setInputCloud(plane_cloud); - proj.setModelCoefficients(coefficients); - proj.filter(*cloud_projected); - - //generate a convex hull - pcl::PointCloud::Ptr cloud_hull (new pcl::PointCloud); - pcl::ConvexHull chull; - chull.setInputCloud(cloud_projected); - chull.reconstruct(*cloud_hull); - dataLibrary::fracture_faces_hull.push_back(cloud_hull); - - if(show_rem) + else { - indices_all->indices.insert(indices_all->indices.end(), dataLibrary::clusters[cluster_index].indices.begin(), dataLibrary::clusters[cluster_index].indices.end()); + bool flag = dataLibrary::CheckClusters(dataLibrary::plane_normal_all, centroid_all, dataLibrary::cloud_hull_all, normal, centroid, cloud_projected, cluster_index, length, false); } + } + } - Eigen::Vector3f normal; - normal(0) = nx; - normal(1) = ny; - normal(2) = nz; + if(show_rem) + { + pcl::ExtractIndices eifilter (true); + eifilter.setInputCloud(dataLibrary::cloudxyz); + eifilter.setIndices(indices_all); + eifilter.setNegative(true); + eifilter.filter(*dataLibrary::segmentation_rem); + } + } - if(show_fracture_traces) - { - float length; - if(show_extension_line) - { - bool flag = dataLibrary::CheckClusters(dataLibrary::plane_normal_all, centroid_all, dataLibrary::cloud_hull_all, normal, centroid, cloud_projected, cluster_index, length, true); - } - else - { - bool flag = dataLibrary::CheckClusters(dataLibrary::plane_normal_all, centroid_all, dataLibrary::cloud_hull_all, normal, centroid, cloud_projected, cluster_index, length, false); - } - } - } + is_success = true; + //end of processing - if(show_rem) - { - pcl::ExtractIndices eifilter (true); - eifilter.setInputCloud(dataLibrary::cloudxyz); - eifilter.setIndices(indices_all); - eifilter.setNegative(true); - eifilter.filter(*dataLibrary::segmentation_rem); - } + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text_head = "\tShowProcess ("; + std::string log_text_body = ""; + for(int i=0; igetMuteMode()&&is_success) + { emit show(); - - dataLibrary::Status = STATUS_READY; - emit showReadyStatus(); } + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); if(this->getWorkFlowMode()&&is_success) { this->Sleep(1000); diff --git a/ShowSFeatureWorker.cpp b/ShowSFeatureWorker.cpp new file mode 100644 index 0000000..36e10c5 --- /dev/null +++ b/ShowSFeatureWorker.cpp @@ -0,0 +1,216 @@ +/* + * Software License Agreement (BSD License) + * + * Xin Wang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author : Xin Wang + * Email : ericrussell@zju.edu.cn + * + */ + +#include +#include +#include +#include +#include +#include +#include "ShowSFeatureWorker.h" +#include "globaldef.h" +#include "dataLibrary.h" + +void ShowSFeatureWorker::doWork() +{ + bool is_success(false); + + dataLibrary::Status = STATUS_SHOWSFEATURE; + + dataLibrary::start = clock(); + + if(dataLibrary::FeatureParameter.feature_type == FEATURE_ROUGHNESS) + { + if(dataLibrary::roughnesses.size() == 0) + { + emit showErrors(QString("ShowSFeatures (roughness): Please save the clusters first.")); + } + else if(dataLibrary::FeatureParameter.percent_out<0.0 || dataLibrary::FeatureParameter.percent_out>0.5) + { + emit showErrors(QString("ShowSFeatures (roughness): Percentage Out was not correctly provided.")); + } + else + { + //begin of processing + //Clear data if needed + if(!dataLibrary::cloudxyzrgb_features->empty()) + dataLibrary::cloudxyzrgb_features->clear(); + pcl::copyPointCloud(*dataLibrary::cloudxyzrgb_clusters, *dataLibrary::cloudxyzrgb_features); + + for(int i=0; ipoints.size(); i++) + { + dataLibrary::cloudxyzrgb_features->at(i).r = 255; + dataLibrary::cloudxyzrgb_features->at(i).g = 255; + dataLibrary::cloudxyzrgb_features->at(i).b = 255; + } + + std::vector temp_roughness(dataLibrary::roughnesses); + std::sort(temp_roughness.begin(), temp_roughness.end()); + float max_val = temp_roughness[(int)(temp_roughness.size()*(1.0-dataLibrary::FeatureParameter.percent_out))]; + float min_val = temp_roughness[(int)(temp_roughness.size()*dataLibrary::FeatureParameter.percent_out)]; + + for(int cluster_index = 0; cluster_index < dataLibrary::clusters.size(); cluster_index++) + { + unsigned char r, g, b; + if(dataLibrary::roughnesses[cluster_index]>max_val) + { + r=255;g=0;b=0; + } + else if(dataLibrary::roughnesses[cluster_index]at(dataLibrary::clusters[cluster_index].indices[j]).r = r; + dataLibrary::cloudxyzrgb_features->at(dataLibrary::clusters[cluster_index].indices[j]).g = g; + dataLibrary::cloudxyzrgb_features->at(dataLibrary::clusters[cluster_index].indices[j]).b = b; + } + } + + is_success = true; + //end of processing + } + } + else if(dataLibrary::FeatureParameter.feature_type == FEATURE_AREA) + { + if(dataLibrary::areas.size() == 0) + { + emit showErrors(QString("ShowSFeatures (area): Please save the clusters first.")); + } + else if(dataLibrary::FeatureParameter.percent_out<0.0 || dataLibrary::FeatureParameter.percent_out>0.5) + { + emit showErrors(QString("ShowSFeatures (area): Percentage Out was not correctly provided.")); + } + else + { + //begin of processing + //Clear data if needed + if(!dataLibrary::cloudxyzrgb_features->empty()) + dataLibrary::cloudxyzrgb_features->clear(); + pcl::copyPointCloud(*dataLibrary::cloudxyzrgb_clusters, *dataLibrary::cloudxyzrgb_features); + + for(int i=0; ipoints.size(); i++) + { + dataLibrary::cloudxyzrgb_features->at(i).r = 255; + dataLibrary::cloudxyzrgb_features->at(i).g = 255; + dataLibrary::cloudxyzrgb_features->at(i).b = 255; + } + + std::vector temp_area(dataLibrary::areas); + std::sort(temp_area.begin(), temp_area.end()); + float max_val = temp_area[(int)(temp_area.size()*(1.0-dataLibrary::FeatureParameter.percent_out))]; + float min_val = temp_area[(int)(temp_area.size()*dataLibrary::FeatureParameter.percent_out)]; + + for(int cluster_index = 0; cluster_index < dataLibrary::clusters.size(); cluster_index++) + { + unsigned char r, g, b; + if(dataLibrary::areas[cluster_index]>max_val) + { + r=255;g=0;b=0; + } + else if(dataLibrary::areas[cluster_index]at(dataLibrary::clusters[cluster_index].indices[j]).r = r; + dataLibrary::cloudxyzrgb_features->at(dataLibrary::clusters[cluster_index].indices[j]).g = g; + dataLibrary::cloudxyzrgb_features->at(dataLibrary::clusters[cluster_index].indices[j]).b = b; + } + } + + is_success = true; + //end of processing + } + } + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tShowSFeature Costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(); + } + + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); + if(this->getWorkFlowMode()&&is_success) + { + this->Sleep(1000); + emit GoWorkFlow(); + } +} \ No newline at end of file diff --git a/ShowSFeatureWorker.h b/ShowSFeatureWorker.h new file mode 100644 index 0000000..e12559e --- /dev/null +++ b/ShowSFeatureWorker.h @@ -0,0 +1,60 @@ +/* + * Software License Agreement (BSD License) + * + * Xin Wang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author : Xin Wang + * Email : ericrussell@zju.edu.cn + * + */ + +#pragma once +#include +#include "Worker.h" +#include "globaldef.h" + +class ShowSFeatureWorker : public Worker +{ + Q_OBJECT + +public: + void showSFeature() + { + QMetaObject::invokeMethod(this, "doWork"); + } + +public slots: + void doWork(); + +signals: + void show(); +}; \ No newline at end of file diff --git a/StaticROWorker.cpp b/StaticROWorker.cpp index 258506e..712c2d3 100755 --- a/StaticROWorker.cpp +++ b/StaticROWorker.cpp @@ -37,6 +37,9 @@ * */ +#include +#include +#include #include #include #include @@ -52,19 +55,50 @@ void StaticROWorker::doWork(const double &stdDev) dataLibrary::Status = STATUS_STATICRO; + dataLibrary::start = clock(); + + //begin of processing pcl::StatisticalOutlierRemoval sor; sor.setInputCloud(dataLibrary::cloudxyz); sor.setMeanK(50); sor.setStddevMulThresh(stdDev); + if(!dataLibrary::outlier_removed_outlier->empty()) + { + dataLibrary::outlier_removed_outlier->clear(); + } sor.setNegative(true); sor.filter(*dataLibrary::outlier_removed_outlier); + if(!dataLibrary::outlier_removed_inlier->empty()) + { + dataLibrary::outlier_removed_inlier->clear(); + } sor.setNegative(false); sor.filter(*dataLibrary::outlier_removed_inlier); - emit show(); + dataLibrary::temp_cloud->clear(); + *dataLibrary::temp_cloud = *dataLibrary::outlier_removed_inlier; + is_success = true; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tStatistical Outlier Removing costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(); + } + dataLibrary::Status = STATUS_READY; emit showReadyStatus(); if(this->getWorkFlowMode()&&is_success) diff --git a/TestWorker.cpp b/TestWorker.cpp new file mode 100644 index 0000000..3359734 --- /dev/null +++ b/TestWorker.cpp @@ -0,0 +1,173 @@ +/* + * Software License Agreement (BSD License) + * + * Xin Wang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author : Xin Wang + * Email : ericrussell@zju.edu.cn + * + */ + +#include +#include +#include +#include +#include +#include +#include "TestWorker.h" +#include "globaldef.h" +#include "dataLibrary.h" + +using namespace std; + +bool transData (const string &filename, const string &savefilename) +{ + ifstream fs; + fs.open (filename.c_str (), ios::binary); + if (!fs.is_open () || fs.fail ()) + { + PCL_ERROR ("Could not open file '%s'! Error : %s\n", filename.c_str (), strerror (errno)); + fs.close (); + return (false); + } + + ofstream transedData_out; + transedData_out.open(savefilename.c_str()); + if (!transedData_out.is_open () || transedData_out.fail ()) + { + PCL_ERROR ("Could not open file '%s'! Error : %s\n", savefilename.c_str (), strerror (errno)); + transedData_out.close (); + return (false); + } + + string line; + vector st; + + while (!fs.eof ()) + { + getline (fs, line); + // Ignore empty lines + if (line == "") + continue; + + // Tokenize the line + boost::trim (line); + boost::split (st, line, boost::is_any_of (",\t\r "), boost::token_compress_on); + + if (st.size () < 3) + continue; + + if (st[0] == "x") + continue; + + transedData_out<substr(0, strfilename->size()-13) += "_XYZ.txt"; + + dataLibrary::Status = STATUS_TESTING; + + //begin of processing + if(transData (*strfilename, transedData)) + { + is_success = true; + } + else + { + emit showErrors("Error transform data."); + } + //end of processing + + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); + delete strfilename; + if(this->getWorkFlowMode()&&is_success) + { + this->Sleep(1000); + emit GoWorkFlow(); + } +}*/ + +void TestWorker::doWork(const QString &filename) +{ + bool is_success(false); + + QByteArray ba = filename.toLocal8Bit(); + string* strfilename = new std::string(ba.data()); + + dataLibrary::Status = STATUS_TESTING; + + //begin of processing + if(!pcl::io::loadPCDFile (*strfilename, *dataLibrary::cloudxyzrgb)) + { + dataLibrary::cloudID = *strfilename; + pcl::PointCloudXYZRGBtoXYZI (*dataLibrary::cloudxyzrgb, *dataLibrary::cloudxyzi); + + if(!this->getMuteMode()) + { + emit ReadFileReady(CLOUDXYZI); + } + is_success = true; + } + else + { + emit showErrors("Error opening pcd file."); + } + //end of processing + + dataLibrary::Status = STATUS_READY; + emit showReadyStatus(); + delete strfilename; + if(this->getWorkFlowMode()&&is_success) + { + this->Sleep(1000); + emit GoWorkFlow(); + } +} \ No newline at end of file diff --git a/TestWorker.h b/TestWorker.h new file mode 100644 index 0000000..aa37962 --- /dev/null +++ b/TestWorker.h @@ -0,0 +1,74 @@ +/* + * Software License Agreement (BSD License) + * + * Xin Wang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author : Xin Wang + * Email : ericrussell@zju.edu.cn + * + */ + +#pragma once +#include "Worker.h" +class TestWorker : public Worker +{ + Q_OBJECT + +public: + TestWorker() : Worker() + { + _is_split = false; + } + + void testing(const QString &filename) + { + QMetaObject::invokeMethod(this, "doWork", Q_ARG(const QString &, filename)); + } + + void setSplitMode(bool mode) + { + _is_split = mode; + } + bool getSplitMode() + { + return _is_split; + } + +private slots: + void doWork(const QString &filename); + +signals: + void ReadFileReady(int i); + +private: + bool _is_split; +}; \ No newline at end of file diff --git a/Worker.h b/Worker.h index b9daac7..a2facb0 100755 --- a/Worker.h +++ b/Worker.h @@ -50,6 +50,8 @@ class Worker : public QObject Worker() : QObject() { _workflow_mode = false; + _is_mute = false; + _write_log = true; moveToThread(&t); t.start(); } @@ -65,6 +67,8 @@ class Worker : public QObject void showReadyStatus(); private: bool _workflow_mode; + bool _is_mute; + bool _write_log; public: void setWorkFlowMode(bool mode) { @@ -74,6 +78,30 @@ class Worker : public QObject { return _workflow_mode; } + void setMute() + { + _is_mute = true; + } + void setUnmute() + { + _is_mute = false; + } + bool getMuteMode() + { + return _is_mute; + } + void setWriteLog() + { + _write_log = true; + } + void setUnWriteLog() + { + _write_log = false; + } + bool getWriteLogMpde() + { + return _write_log; + } void Sleep(unsigned long ms) { t.Sleep(ms); diff --git a/dataLibrary.cpp b/dataLibrary.cpp index f675687..8c82f4f 100755 --- a/dataLibrary.cpp +++ b/dataLibrary.cpp @@ -44,8 +44,10 @@ using namespace std; pcl::PointCloud::Ptr dataLibrary::cloudxyz(new pcl::PointCloud); pcl::PointCloud::Ptr dataLibrary::cloudxyzrgb(new pcl::PointCloud); +pcl::PointCloud::Ptr dataLibrary::cloudxyzi(new pcl::PointCloud); pcl::PointCloud::Ptr dataLibrary::cloudxyzrgb_clusters(new pcl::PointCloud); -sensor_msgs::PointCloud2::Ptr dataLibrary::cloud_blob(new sensor_msgs::PointCloud2); +pcl::PointCloud::Ptr dataLibrary::cloudxyzrgb_features(new pcl::PointCloud); +pcl::PCLPointCloud2::Ptr dataLibrary::cloud_blob(new pcl::PCLPointCloud2); pcl::PointCloud::Ptr dataLibrary::normal (new pcl::PointCloud); pcl::PointCloud::Ptr dataLibrary::pointnormals(new pcl::PointCloud); pcl::PointCloud::Ptr dataLibrary::mls_points(new pcl::PointCloud); @@ -62,12 +64,14 @@ std::vector dataLibrary::dip_directions; std::vector dataLibrary::out_dips; std::vector dataLibrary::out_dip_directions; std::vector dataLibrary::areas; +std::vector dataLibrary::roughnesses; std::vector dataLibrary::patchIDs; int dataLibrary::currentPatch(0); std::vector dataLibrary::selectedPatches; std::string dataLibrary::cloudID(""); int dataLibrary::Status(STATUS_READY); RGSpara dataLibrary::RGSparameter; +FeaturePara dataLibrary::FeatureParameter; std::vector dataLibrary::contents; pcl::PointCloud::Ptr dataLibrary::cloud_hull_all (new pcl::PointCloud); Eigen::Vector3f dataLibrary::plane_normal_all; @@ -77,6 +81,8 @@ std::vector dataLibrary::Lines_min; std::vector dataLibrary::Workflow; int dataLibrary::current_workline_index = 0; bool dataLibrary::have_called_read_file = false; +clock_t dataLibrary::start; +clock_t dataLibrary::finish; void dataLibrary::checkupflow() { @@ -474,4 +480,10 @@ bool dataLibrary::checkContents(std::vector contents, std::string q } } return false; +} + +void dataLibrary::write_text_to_log_file(const std::string &text) +{ + std::ofstream log_file ("log_file.txt", std::ios_base::out | std::ios_base::app); + log_file << text << std::endl; } \ No newline at end of file diff --git a/dataLibrary.h b/dataLibrary.h index e116868..2ac8a84 100755 --- a/dataLibrary.h +++ b/dataLibrary.h @@ -38,10 +38,13 @@ */ #pragma once +#include +#include #include #include #include #include +#include #include #include "ReadFileWorker.h" #include "checkstatusThread.h" @@ -52,8 +55,10 @@ class dataLibrary public: static pcl::PointCloud::Ptr cloudxyz; static pcl::PointCloud::Ptr cloudxyzrgb; - static pcl::PointCloud::Ptr cloudxyzrgb_clusters; - static sensor_msgs::PointCloud2::Ptr cloud_blob; + static pcl::PointCloud::Ptr cloudxyzi; + static pcl::PointCloud::Ptr cloudxyzrgb_clusters; //for showing the segmentation result + static pcl::PointCloud::Ptr cloudxyzrgb_features; //for showing the surface features + static pcl::PCLPointCloud2::Ptr cloud_blob; static pcl::PointCloud::Ptr normal; static pcl::PointCloud::Ptr pointnormals; static pcl::PointCloud::Ptr mls_points; @@ -64,18 +69,20 @@ class dataLibrary static pcl::PointCloud::Ptr segmentation_rem; static std::string cloudID; static std::vector clusters; - static std::vector::Ptr> cluster_patches; + static std::vector::Ptr> cluster_patches; //for reading in the saved clusters data static std::vector::Ptr> fracture_faces_hull; static std::vector dips; static std::vector dip_directions; static std::vector out_dips; static std::vector out_dip_directions; static std::vector areas; + static std::vector roughnesses; static std::vector patchIDs; static int currentPatch; static std::vector selectedPatches; static int Status; static RGSpara RGSparameter; + static FeaturePara FeatureParameter; static std::vector contents; static pcl::PointCloud::Ptr cloud_hull_all; static Eigen::Vector3f plane_normal_all; @@ -85,6 +92,8 @@ class dataLibrary static std::vector Workflow; static int current_workline_index; static bool have_called_read_file; + static clock_t start; + static clock_t finish; public: static void checkupflow(); @@ -104,4 +113,5 @@ class dataLibrary static bool isSegmentCrossPolygon(const Eigen::Vector2f &point_a, const Eigen::Vector2f &point_b, const std::vector &convex_hull); static bool CheckClusters(const Eigen::Vector3f &V, const Eigen::Vector3f &xyz_centroid, pcl::PointCloud::Ptr convex_hull, const Eigen::Vector3f &V_i, const Eigen::Vector3f &xyz_centroid_i, pcl::PointCloud::Ptr projected_i, int patchNum, float &length, bool needExLine); static bool checkContents(std::vector contents, std::string query); + static void write_text_to_log_file (const std::string &text); }; \ No newline at end of file diff --git a/doc/doc.md b/doc/doc.md deleted file mode 100755 index 191f80b..0000000 --- a/doc/doc.md +++ /dev/null @@ -1,65 +0,0 @@ -## Processing actions - -### openpcd - - - -### openbin - - - -### openxyz - - - -### savepcdascii - - - -### savepcdbinary - - - -### savenormals - - - -### saveclusters - - - -### downsample - - - -### resample - - - -### knnormal - - - -### ranormal - - - -### rostatic - - - -### rgsegmentation - - - -### quitsession - - - -### showstereonet - - - -### showprocess - - diff --git a/downsampleWorker.cpp b/downsampleWorker.cpp index b882d9c..cd9462f 100755 --- a/downsampleWorker.cpp +++ b/downsampleWorker.cpp @@ -37,6 +37,9 @@ * */ +#include +#include +#include #include #include #include @@ -51,14 +54,42 @@ void downsampleWorker::doWork(const double &leaf) dataLibrary::checkupflow(); dataLibrary::Status = STATUS_DOWNSAMPLE; + + dataLibrary::start = clock(); + + //begin of processing // Create the filtering object pcl::VoxelGrid sor; sor.setInputCloud (dataLibrary::cloudxyz); sor.setLeafSize (leaf, leaf, leaf); + if(!dataLibrary::downsampledxyz->empty()) + { + dataLibrary::downsampledxyz->clear(); + } sor.filter (*dataLibrary::downsampledxyz); - emit show(); + dataLibrary::temp_cloud->clear(); + *dataLibrary::temp_cloud = *dataLibrary::downsampledxyz; + is_success = true; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tDownsampling costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(); + } + dataLibrary::Status = STATUS_READY; emit showReadyStatus(); if(this->getWorkFlowMode()&&is_success) diff --git a/globaldef.h b/globaldef.h index 5efdae9..8b4ce61 100755 --- a/globaldef.h +++ b/globaldef.h @@ -44,6 +44,7 @@ #define CLOUDXYZ 1 #define CLOUDXYZRGB 2 +#define CLOUDXYZI 3 #define EPSILON 0.0000001 #define TWOPI 6.283185307179586476925287 @@ -61,6 +62,11 @@ #define STATUS_SAVEBINARY 111 #define STATUS_SAVENORMALS 112 #define STATUS_SHOWPROCESS 113 +#define STATUS_TESTING 114 +#define STATUS_SHOWSFEATURE 115 + +#define FEATURE_ROUGHNESS 1001 +#define FEATURE_AREA 1002 struct RGSpara{ double curvature; @@ -71,6 +77,11 @@ struct RGSpara{ bool IsSmoothMode; }; +struct FeaturePara{ + int feature_type; + float percent_out; +}; + struct Vector3f{ float x, y, z; }; diff --git a/knnormalWorker.cpp b/knnormalWorker.cpp index 1df2fe5..ebda6aa 100755 --- a/knnormalWorker.cpp +++ b/knnormalWorker.cpp @@ -37,6 +37,9 @@ * */ +#include +#include +#include #include #include #include @@ -53,16 +56,45 @@ void knnormalWorker::doWork(const int &k) dataLibrary::Status = STATUS_KNNORMAL; + dataLibrary::start = clock(); + + //begin of processing pcl::NormalEstimationOMP ne; ne.setInputCloud(dataLibrary::cloudxyz); pcl::search::KdTree::Ptr tree (new pcl::search::KdTree()); ne.setSearchMethod(tree); ne.setKSearch(k); - + if(!dataLibrary::normal->empty()) + { + dataLibrary::normal->clear(); + } ne.compute(*dataLibrary::normal); - emit show(); + if(!dataLibrary::pointnormals->empty()) + { + dataLibrary::pointnormals->clear(); + } + pcl::concatenateFields(*dataLibrary::cloudxyz, *dataLibrary::normal, *dataLibrary::pointnormals); + is_success = true; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tComputing K Nearest Neighbor Normal costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(_show_curvature); + } + dataLibrary::Status = STATUS_READY; emit showReadyStatus(); if(this->getWorkFlowMode()&&is_success) diff --git a/knnormalWorker.h b/knnormalWorker.h index 0f2c848..a5628e8 100755 --- a/knnormalWorker.h +++ b/knnormalWorker.h @@ -45,14 +45,31 @@ class knnormalWorker : Q_OBJECT public: + knnormalWorker() : Worker() + { + _show_curvature = false; + } + void knnormal(const int &k) { QMetaObject::invokeMethod(this, "doWork", Q_ARG(const int &, k)); } + void setShowCurvature(bool mode) + { + _show_curvature = mode; + } + bool getShowCurvature() + { + return _show_curvature; + } + private slots: void doWork(const int &k); signals: - void show(); + void show(bool _show_curvature); + +private: + bool _show_curvature; }; \ No newline at end of file diff --git a/ranormalWorker.cpp b/ranormalWorker.cpp index 1800a7b..470c58d 100755 --- a/ranormalWorker.cpp +++ b/ranormalWorker.cpp @@ -37,6 +37,9 @@ * */ +#include +#include +#include #include #include #include @@ -53,15 +56,44 @@ void ranormalWorker::doWork(const double &radius) dataLibrary::Status = STATUS_RANORMAL; + dataLibrary::start = clock(); + + //begin of processing pcl::NormalEstimationOMP ne; ne.setInputCloud(dataLibrary::cloudxyz); pcl::search::KdTree::Ptr tree (new pcl::search::KdTree()); ne.setSearchMethod(tree); ne.setRadiusSearch(radius); + if(!dataLibrary::normal->empty()) + { + dataLibrary::normal->clear(); + } ne.compute(*dataLibrary::normal); - emit show(); + if(!dataLibrary::pointnormals->empty()) + { + dataLibrary::pointnormals->clear(); + } + pcl::concatenateFields(*dataLibrary::cloudxyz, *dataLibrary::normal, *dataLibrary::pointnormals); + is_success = true; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tComputing Radius Normal costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(_show_curvature); + } dataLibrary::Status = STATUS_READY; emit showReadyStatus(); if(this->getWorkFlowMode()&&is_success) diff --git a/ranormalWorker.h b/ranormalWorker.h index 600d395..63eee42 100755 --- a/ranormalWorker.h +++ b/ranormalWorker.h @@ -45,15 +45,32 @@ class ranormalWorker : Q_OBJECT public: + ranormalWorker() : Worker() + { + _show_curvature = false; + } + void ranormal(const double &radius) { QMetaObject::invokeMethod(this, "doWork", Q_ARG(const double &, radius)); } + + void setShowCurvature(bool mode) + { + _show_curvature = mode; + } + bool getShowCurvature() + { + return _show_curvature; + } private slots: void doWork(const double &radius); signals: - void show(); + void show(bool _show_curvature); + +private: + bool _show_curvature; }; diff --git a/resampleWorker.cpp b/resampleWorker.cpp index 69b79cb..6a1a036 100755 --- a/resampleWorker.cpp +++ b/resampleWorker.cpp @@ -37,6 +37,9 @@ * */ +#include +#include +#include #include #include #include @@ -47,10 +50,15 @@ void resampleWorker::doWork(const double &radius) { + bool is_success(false); + dataLibrary::checkupflow(); dataLibrary::Status = STATUS_RESAMPLE; + + dataLibrary::start = clock(); + //begin of processing // Create a KD-Tree pcl::search::KdTree::Ptr tree (new pcl::search::KdTree); @@ -66,13 +74,39 @@ void resampleWorker::doWork(const double &radius) mls.setSearchRadius (radius); // Reconstruct - mls.process (*dataLibrary::mls_points); - - emit show(); - if(this->getWorkFlowMode()) + if(!dataLibrary::mls_points->empty()) { - emit GoWorkFlow(); + dataLibrary::mls_points->clear(); } + mls.process (*dataLibrary::mls_points); + + dataLibrary::temp_cloud->clear(); + *dataLibrary::temp_cloud = *dataLibrary::mls_points; + + is_success = true; + //end of processing + + dataLibrary::finish = clock(); + + if(this->getWriteLogMpde()&&is_success) + { + std::string log_text = "\tResampling costs: "; + std::ostringstream strs; + strs << (double)(dataLibrary::finish-dataLibrary::start)/CLOCKS_PER_SEC; + log_text += (strs.str() +" seconds."); + dataLibrary::write_text_to_log_file(log_text); + } + + if(!this->getMuteMode()&&is_success) + { + emit show(); + } + dataLibrary::Status = STATUS_READY; emit showReadyStatus(); + if(this->getWorkFlowMode()&&is_success) + { + this->Sleep(1000); + emit GoWorkFlow(); + } } diff --git a/structrock.cpp b/structrock.cpp index e0dd8d0..d39050b 100755 --- a/structrock.cpp +++ b/structrock.cpp @@ -38,15 +38,24 @@ */ #include +#include #include #include +#include #include +#include #include +#include +#include "pcl/common/common_headers.h" #include #include #include +#include #include #include +//begin kinect v2 +#include +//end kinect v2 #include #include #include @@ -61,6 +70,9 @@ #include #include #include +//begin kinect v2 +#include +//end kinect v2 #include #include #include @@ -81,18 +93,26 @@ #include "SaveClustersWorker.h" #include "ReadXYZWorker.h" #include "ShowProcessWorker.h" +#include "ShowSFeatureWorker.h" +#include "TestWorker.h" #include "globaldef.h" #include "dataLibrary.h" #include "structrock.h" #include "geo_region_growing.h" #include "plotwindow.h" #include "TimingShutdown.h" +//begin kinect v2 +#include "KinectV2Viewer.h" +//end kinect v2 using namespace std; structrock::structrock(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags), viewer(new pcl::visualization::PCLVisualizer("3D Viewer")), + //begin kinect v2 + imageViewer(vtkImageViewer2::New()), + //end kinect v2 v1(1), v2(2) { @@ -202,6 +222,16 @@ structrock::structrock(QWidget *parent, Qt::WFlags flags) QMenu *segmentation = edit->addMenu(tr("&Segmentation")); segmentation->addAction(region_growing_segmentation); + + //begin kinect v2 + QMenu *kinect = menuBar()->addMenu(tr("&Kinect")); + connect_Kinect = new QAction(tr("&Connect"), this); + connect(connect_Kinect, SIGNAL(triggered()), this, SLOT(Connect_Kinect())); + disconnect_Kinect = new QAction(tr("&Disconnect"), this); + connect(disconnect_Kinect, SIGNAL(triggered()), this, SLOT(Disconnect_Kinect())); + kinect->addAction(connect_Kinect); + kinect->addAction(disconnect_Kinect); + //end kinect v2 testing = new QAction(tr("&Test"), this); connect(testing, SIGNAL(triggered()), this, SLOT(Testing())); @@ -215,7 +245,6 @@ structrock::structrock(QWidget *parent, Qt::WFlags flags) help->addAction(stereonet); help->addAction(testing); - checkstatusThread *csThread(new checkstatusThread); connect(csThread, SIGNAL(show(int)), this, SLOT(ShowStatus(int))); connect(csThread, SIGNAL(finished()), csThread, SLOT(deleteLater())); @@ -224,9 +253,31 @@ structrock::structrock(QWidget *parent, Qt::WFlags flags) structrock::~structrock() { - + +} + +//begin kinect v2 +void structrock::Connect_Kinect() +{ + boost::shared_ptr deviceManager = pcl::io::openni2::OpenNI2DeviceManager::getInstance (); + if (deviceManager->getNumOfConnectedDevices () > 0) + { + grabber = new pcl::io::OpenNI2Grabber("", pcl::io::OpenNI2Grabber::OpenNI_Default_Mode, pcl::io::OpenNI2Grabber::OpenNI_Default_Mode); + KinectV2Viewer openni_viewer (grabber, viewer); + openni_viewer.run(); + } + else + { + Show_Errors(QString("No Kinect Senser Devices Connected!")); + } } +void structrock::Disconnect_Kinect() +{ + if (grabber && grabber->isRunning ()) grabber->stop (); +} +//end kinect v2 + void structrock::open() { QString filename = QFileDialog::getOpenFileName(NULL,tr("Open Point Cloud Data"),QDir::currentPath(),tr("Point Cloud Data (*.pcd);;All files (*.*)")); @@ -234,6 +285,7 @@ void structrock::open() if(!filename.isNull()) { readfileworker.setWorkFlowMode(false); + readfileworker.setUnmute(); QObject::connect(&readfileworker, SIGNAL(ReadFileReady(int)), this, SLOT(ShowPCD(int))); connect(&readfileworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); QObject::connect(&readfileworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -249,6 +301,7 @@ void structrock::OpenXYZ() if(!filename.isNull()) { readxyzworker.setWorkFlowMode(false); + readxyzworker.setUnmute(); connect(&readxyzworker, SIGNAL(ReadXYZReady(int)), this, SLOT(ShowPCD(int))); connect(&readxyzworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&readxyzworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -425,453 +478,818 @@ void structrock::command_parser() if(dataLibrary::Workflow.size()!=0) { if(dataLibrary::current_workline_index0) + bool need_move_on(true); + + std::string command_string = dataLibrary::Workflow[dataLibrary::current_workline_index].command; + std::transform(command_string.begin(), command_string.end(), command_string.begin(), ::tolower); + if(command_string == "openpcd") { - if(!dataLibrary::have_called_read_file) - { - readfileworker.setWorkFlowMode(true); - QObject::connect(&readfileworker, SIGNAL(ReadFileReady(int)), this, SLOT(ShowPCD(int))); - QObject::connect(&readfileworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - QObject::connect(&readfileworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - QObject::connect(&readfileworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - readfileworker.readFile(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); - dataLibrary::have_called_read_file = true; - } - else + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) { - std::string commands = ""; - for(int i=dataLibrary::current_workline_index; i0) + readfileworker.setWorkFlowMode(true); + readfileworker.setUnmute(); + readfileworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + readfileworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + readfileworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + readfileworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + readfileworker.setUnWriteLog(); + } + } + } + QObject::connect(&readfileworker, SIGNAL(ReadFileReady(int)), this, SLOT(ShowPCD(int))); + QObject::connect(&readfileworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + QObject::connect(&readfileworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + QObject::connect(&readfileworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + readfileworker.readFile(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + dataLibrary::have_called_read_file = true; + } + else + { + std::string commands = ""; + for(int i=dataLibrary::current_workline_index; i0) { - commands += dataLibrary::Workflow[i].parameters[j]; + commands += dataLibrary::Workflow[i].command; commands += ","; + for(int j=0; jsetWorkingDirectory(QApplication::applicationDirPath()); + #if !defined(_WIN32)&&(defined(__unix__)||defined(__unix)||(defined(__APPLE__)&&defined(__MACH__))) + myProcess->start("./structrock",commandsList); + #elif defined(_WIN32)||defined(_WIN64) + myProcess->start("structrock",commandsList); + #endif } - #if defined(_WIN32)||defined(_WIN64) - size_t f = commands.find("\\"); - commands.replace(f, std::string("\\").length(), "\\\\"); - #endif - - QProcess *myProcess = new QProcess; - QStringList commandsList; - commandsList << "-c"<setWorkingDirectory(QApplication::applicationDirPath()); - #if !defined(_WIN32)&&(defined(__unix__)||defined(__unix)||(defined(__APPLE__)&&defined(__MACH__))) - myProcess->start("./structrock",commandsList); - #elif defined(_WIN32)||defined(_WIN64) - myProcess->start("structrock",commandsList); - #endif + } + else + { + Show_Errors(QString("Openpcd: Location of PCD file not provided.")); } } - else + else if(command_string == "openbin") { - Show_Errors(QString("Openpcd: Location of PCD file not provided.")); + } - } - else if(command_string == "openbin") - { - - } - else if(command_string == "openxyz") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "openxyz") { - if(!dataLibrary::have_called_read_file) - { - readxyzworker.setWorkFlowMode(true); - connect(&readxyzworker, SIGNAL(ReadXYZReady(int)), this, SLOT(ShowPCD(int))); - connect(&readxyzworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&readxyzworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&readxyzworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - readxyzworker.readXYZ(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); - dataLibrary::have_called_read_file = true; - } - else + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) { - std::string commands = ""; - for(int i=dataLibrary::current_workline_index; i0) + readxyzworker.setWorkFlowMode(true); + readxyzworker.setUnmute(); + readxyzworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + readxyzworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + readxyzworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + readxyzworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + readxyzworker.setUnWriteLog(); + } + } + } + connect(&readxyzworker, SIGNAL(ReadXYZReady(int)), this, SLOT(ShowPCD(int))); + connect(&readxyzworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&readxyzworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&readxyzworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + readxyzworker.readXYZ(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + dataLibrary::have_called_read_file = true; + } + else + { + std::string commands = ""; + for(int i=dataLibrary::current_workline_index; i0) { - commands += dataLibrary::Workflow[i].parameters[j]; + commands += dataLibrary::Workflow[i].command; commands += ","; + for(int j=0; jsetWorkingDirectory(QApplication::applicationDirPath()); + #if !defined(_WIN32)&&(defined(__unix__)||defined(__unix)||(defined(__APPLE__)&&defined(__MACH__))) + myProcess->start("./structrock",commandsList); + #elif defined(_WIN32)||defined(_WIN64) + myProcess->start("structrock",commandsList); + #endif } - - #if defined(_WIN32)||defined(_WIN64) - size_t f = commands.find("\\"); - commands.replace(f, std::string("\\").length(), "\\\\"); - #endif - - QProcess *myProcess = new QProcess; - QStringList commandsList; - commandsList << "-c"<setWorkingDirectory(QApplication::applicationDirPath()); - #if !defined(_WIN32)&&(defined(__unix__)||defined(__unix)||(defined(__APPLE__)&&defined(__MACH__))) - myProcess->start("./structrock",commandsList); - #elif defined(_WIN32)||defined(_WIN64) - myProcess->start("structrock",commandsList); - #endif + } + else + { + Show_Errors(QString("Openxyz: Location of XYZ file not provided.")); } } - else - { - Show_Errors(QString("Openxyz: Location of XYZ file not provided.")); - } - } - else if(command_string == "savepcdascii") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "savepcdascii") { - savepcdASCIIworker.setWorkFlowMode(true); - connect(&savepcdASCIIworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&savepcdASCIIworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&savepcdASCIIworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + savepcdASCIIworker.setWorkFlowMode(true); + connect(&savepcdASCIIworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&savepcdASCIIworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&savepcdASCIIworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - savepcdASCIIworker.saveascii(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); - } - else - { - Show_Errors(QString("Savepcdascii: Save path not provided.")); + savepcdASCIIworker.saveascii(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + } + else + { + Show_Errors(QString("Savepcdascii: Save path not provided.")); + } } - } - else if(command_string == "savepcdbinary") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "savepcdbinary") { - savepcdBinaryworker.setWorkFlowMode(true); - connect(&savepcdBinaryworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&savepcdBinaryworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&savepcdBinaryworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + savepcdBinaryworker.setWorkFlowMode(true); + connect(&savepcdBinaryworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&savepcdBinaryworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&savepcdBinaryworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - savepcdBinaryworker.savebinary(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); - } - else - { - Show_Errors(QString("Savepcdbinary: Save path not provided.")); + savepcdBinaryworker.savebinary(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + } + else + { + Show_Errors(QString("Savepcdbinary: Save path not provided.")); + } } - } - else if(command_string == "savenormals") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "savenormals") { - savenormalsworker.setWorkFlowMode(true); - connect(&savenormalsworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&savenormalsworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&savenormalsworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + savenormalsworker.setWorkFlowMode(true); + connect(&savenormalsworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&savenormalsworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&savenormalsworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - savenormalsworker.savenormals(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); - } - else - { - Show_Errors(QString("Savenormals: Save path not provided.")); - } - } - else if(command_string == "saveclusters") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) - { - saveclustersworker.setWorkFlowMode(true); - connect(&saveclustersworker, SIGNAL(SaveClustersReady(QString)), this, SLOT(ShowSavedClusters(QString))); - connect(&saveclustersworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&saveclustersworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&saveclustersworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - saveclustersworker.saveclusters(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); - } - else - { - Show_Errors(QString("Saveclusters: Save path not provided.")); - } - } - else if(command_string == "downsample") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) - { - double leaf; - std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); - ss >> leaf; - - downsampleworker.setWorkFlowMode(true); - connect(&downsampleworker, SIGNAL(show()), this, SLOT(ShowDownsample())); - connect(&downsampleworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&downsampleworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&downsampleworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - downsampleworker.downsample(leaf); + savenormalsworker.savenormals(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + } + else + { + Show_Errors(QString("Savenormals: Save path not provided.")); + } } - else + else if(command_string == "saveclusters") { - Show_Errors(QString("Downsample: Minimum point distance not given.")); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + saveclustersworker.setWorkFlowMode(true); + saveclustersworker.setUnmute(); + saveclustersworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + saveclustersworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + saveclustersworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + saveclustersworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + saveclustersworker.setUnWriteLog(); + } + } + } + connect(&saveclustersworker, SIGNAL(SaveClustersReady(QString)), this, SLOT(ShowSavedClusters(QString))); + connect(&saveclustersworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&saveclustersworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&saveclustersworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + saveclustersworker.saveclusters(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + } + else + { + Show_Errors(QString("Saveclusters: Save path not provided.")); + } } - } - else if(command_string == "resample") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "downsample") { - double radius; - std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); - ss >> radius; - - resampleworker.setWorkFlowMode(true); - connect(&resampleworker, SIGNAL(show()), this, SLOT(ShowResample())); - connect(&resampleworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&resampleworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&resampleworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - resampleworker.resample(radius); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + double leaf; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); + ss >> leaf; + + downsampleworker.setWorkFlowMode(true); + downsampleworker.setUnmute(); + downsampleworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + downsampleworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + downsampleworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + downsampleworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + downsampleworker.setUnWriteLog(); + } + } + } + connect(&downsampleworker, SIGNAL(show()), this, SLOT(ShowDownsample())); + connect(&downsampleworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&downsampleworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&downsampleworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + downsampleworker.downsample(leaf); + } + else + { + Show_Errors(QString("Downsample: Minimum point distance not given.")); + } } - else + else if(command_string == "resample") { - Show_Errors(QString("Resample: Search radius not given.")); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + double radius; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); + ss >> radius; + + resampleworker.setWorkFlowMode(true); + resampleworker.setUnmute(); + resampleworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + resampleworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + resampleworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + resampleworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + resampleworker.setUnWriteLog(); + } + } + } + connect(&resampleworker, SIGNAL(show()), this, SLOT(ShowResample())); + connect(&resampleworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&resampleworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&resampleworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + resampleworker.resample(radius); + } + else + { + Show_Errors(QString("Resample: Search radius not given.")); + } } - } - else if(command_string == "knnormal") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "knnormal") { - int k; - std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); - ss >> k; - - knnormalworker.setWorkFlowMode(true); - connect(&knnormalworker, SIGNAL(show()), this, SLOT(ShowknNormal())); - connect(&knnormalworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&knnormalworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&knnormalworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + int k; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); + ss >> k; + + knnormalworker.setWorkFlowMode(true); + knnormalworker.setShowCurvature(false); + knnormalworker.setUnmute(); + knnormalworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "showcurvature") + { + knnormalworker.setShowCurvature(true); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + knnormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + knnormalworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>3) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[3] == "mute") + { + knnormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[3] == "nolog") + { + knnormalworker.setUnWriteLog(); + } + } + } + } + else + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + knnormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + knnormalworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + knnormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + knnormalworker.setUnWriteLog(); + } + } + } + } + connect(&knnormalworker, SIGNAL(show()), this, SLOT(ShowknNormal())); + connect(&knnormalworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&knnormalworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&knnormalworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - knnormalworker.knnormal(k); - } - else - { - Show_Errors(QString("Knnormal: Number of neoghbor points not given.")); - } - } - else if(command_string == "ranormal") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) - { - double radius; - std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); - ss >> radius; - - ranormalworker.setWorkFlowMode(true); - connect(&ranormalworker, SIGNAL(show()), this, SLOT(ShowraNormal())); - connect(&ranormalworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&ranormalworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&ranormalworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - ranormalworker.ranormal(radius); - } - else - { - Show_Errors(QString("Ranormal: Search radius not given.")); + knnormalworker.knnormal(k); + } + else + { + Show_Errors(QString("Knnormal: Number of neoghbor points not given.")); + } } - } - else if(command_string == "rostatic") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "ranormal") { - double stdDev; - std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); - ss >> stdDev; - - staticroworker.setWorkFlowMode(true); - connect(&staticroworker, SIGNAL(show()), this, SLOT(ShowSRO())); - connect(&staticroworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&staticroworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&staticroworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - staticroworker.rostatic(stdDev); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + double radius; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); + ss >> radius; + + ranormalworker.setWorkFlowMode(true); + ranormalworker.setShowCurvature(false); + ranormalworker.setUnmute(); + ranormalworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "showcurvature") + { + ranormalworker.setShowCurvature(true); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + ranormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + ranormalworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>3) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[3] == "mute") + { + ranormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[3] == "nolog") + { + ranormalworker.setUnWriteLog(); + } + } + } + } + else + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + ranormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + ranormalworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + ranormalworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + ranormalworker.setUnWriteLog(); + } + } + } + } + connect(&ranormalworker, SIGNAL(show()), this, SLOT(ShowraNormal())); + connect(&ranormalworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&ranormalworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&ranormalworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + ranormalworker.ranormal(radius); + } + else + { + Show_Errors(QString("Ranormal: Search radius not given.")); + } } - else + else if(command_string == "rostatic") { - Show_Errors(QString("Standard deviation not given.")); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + double stdDev; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); + ss >> stdDev; + + staticroworker.setWorkFlowMode(true); + staticroworker.setUnmute(); + staticroworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "mute") + { + staticroworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "nolog") + { + staticroworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>2) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "mute") + { + staticroworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2] == "nolog") + { + staticroworker.setUnWriteLog(); + } + } + } + connect(&staticroworker, SIGNAL(show()), this, SLOT(ShowSRO())); + connect(&staticroworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&staticroworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&staticroworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + staticroworker.rostatic(stdDev); + } + else + { + Show_Errors(QString("Standard deviation not given.")); + } } - } - else if(command_string == "rgsegmentation") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>5) + else if(command_string == "rgsegmentation") { - double smoothness; - std::stringstream ss_smoothness(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); - ss_smoothness >> smoothness; - dataLibrary::RGSparameter.smoothness = smoothness; - double curvature; - std::stringstream ss_curvature(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1]); - ss_curvature >> curvature; - dataLibrary::RGSparameter.curvature = curvature; - double residual; - std::stringstream ss_residual(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2]); - ss_residual >> residual; - dataLibrary::RGSparameter.residual = residual; - int min_number_of_Points; - std::stringstream ss_min_number_of_Points(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[3]); - ss_min_number_of_Points >> min_number_of_Points; - dataLibrary::RGSparameter.min_number_of_Points = min_number_of_Points; - int number_of_neighbors; - std::stringstream ss_number_of_neighbors(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[4]); - ss_number_of_neighbors >> number_of_neighbors; - dataLibrary::RGSparameter.number_of_neighbors = number_of_neighbors; - std::string IsSmoothMode_string = dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[5]; - std::transform(IsSmoothMode_string.begin(), IsSmoothMode_string.end(), IsSmoothMode_string.begin(), ::tolower); - if((IsSmoothMode_string == "true")||(IsSmoothMode_string == "false")) + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>5) { - if(IsSmoothMode_string == "true") + double smoothness; + std::stringstream ss_smoothness(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]); + ss_smoothness >> smoothness; + dataLibrary::RGSparameter.smoothness = smoothness; + double curvature; + std::stringstream ss_curvature(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1]); + ss_curvature >> curvature; + dataLibrary::RGSparameter.curvature = curvature; + double residual; + std::stringstream ss_residual(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[2]); + ss_residual >> residual; + dataLibrary::RGSparameter.residual = residual; + int min_number_of_Points; + std::stringstream ss_min_number_of_Points(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[3]); + ss_min_number_of_Points >> min_number_of_Points; + dataLibrary::RGSparameter.min_number_of_Points = min_number_of_Points; + int number_of_neighbors; + std::stringstream ss_number_of_neighbors(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[4]); + ss_number_of_neighbors >> number_of_neighbors; + dataLibrary::RGSparameter.number_of_neighbors = number_of_neighbors; + std::string IsSmoothMode_string = dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[5]; + std::transform(IsSmoothMode_string.begin(), IsSmoothMode_string.end(), IsSmoothMode_string.begin(), ::tolower); + if((IsSmoothMode_string == "true")||(IsSmoothMode_string == "false")) { - dataLibrary::RGSparameter.IsSmoothMode=true; + if(IsSmoothMode_string == "true") + { + dataLibrary::RGSparameter.IsSmoothMode=true; + } + else if(IsSmoothMode_string == "false") + { + dataLibrary::RGSparameter.IsSmoothMode=false; + } + rgsworker.setWorkFlowMode(true); + rgsworker.setUnmute(); + rgsworker.setWriteLog(); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>6) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[6] == "mute") + { + rgsworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[6] == "nolog") + { + rgsworker.setUnWriteLog(); + } + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>7) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[7] == "mute") + { + rgsworker.setMute(); + } + else if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[7] == "nolog") + { + rgsworker.setUnWriteLog(); + } + } + } + connect(&rgsworker, SIGNAL(show()), this, SLOT(ShowRGS())); + connect(&rgsworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&rgsworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&rgsworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + rgsworker.rgs(); } - else if(IsSmoothMode_string == "false") + else { - dataLibrary::RGSparameter.IsSmoothMode=false; + Show_Errors(QString("Rgsegmentation: IsSmoothMode not set correctly, set with \"true\" or \"false\".")); } - rgsworker.setWorkFlowMode(true); - connect(&rgsworker, SIGNAL(show()), this, SLOT(ShowRGS())); - connect(&rgsworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); - connect(&rgsworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); - connect(&rgsworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); - - rgsworker.rgs(); } else { - Show_Errors(QString("Rgsegmentation: IsSmoothMode not set correctly, set with \"true\" or \"false\".")); + Show_Errors(QString("Rgsegmentation: Not enough parameters given.")); } } - else - { - Show_Errors(QString("Rgsegmentation: Not enough parameters given.")); - } - } - else if(command_string == "showprocess") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "showprocess") { - for(int i=0; i0) + { + for(int i=0; i0) { - if(dataLibrary::Workflow[i].parameters.size()>0) + showsfeatureworker.setWorkFlowMode(true); + showsfeatureworker.setUnmute(); + showsfeatureworker.setWriteLog(); + connect(&showsfeatureworker, SIGNAL(show()), this, SLOT(Show_SFeature())); + connect(&showsfeatureworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&showsfeatureworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&showsfeatureworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + std::string feature_str = dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]; + if(feature_str == "roughness") { - commands += dataLibrary::Workflow[i].command; - commands += ","; - for(int j=0; j1) { - commands += dataLibrary::Workflow[i].parameters[j]; - commands += ","; + float percent_out; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1]); + ss >> percent_out; + dataLibrary::FeatureParameter.percent_out = percent_out; + } + else + { + dataLibrary::FeatureParameter.percent_out = 0.0f; } - commands += dataLibrary::Workflow[i].parameters[dataLibrary::Workflow[i].parameters.size()-1]; - commands += ";"; + showsfeatureworker.showSFeature(); + } + else if(feature_str == "area") + { + dataLibrary::FeatureParameter.feature_type = FEATURE_AREA; + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + float percent_out; + std::stringstream ss(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1]); + ss >> percent_out; + dataLibrary::FeatureParameter.percent_out = percent_out; + } + else + { + dataLibrary::FeatureParameter.percent_out = 0.0f; + } + showsfeatureworker.showSFeature(); } else { - commands += dataLibrary::Workflow[i].command; - commands += ";"; + Show_Errors(QString("ShowSFeatures: the name of the surface feature not correctly provided.")); } } - - #if defined(_WIN32)||defined(_WIN64) - size_t f = commands.find("\\"); - commands.replace(f, std::string("\\").length(), "\\\\"); - #endif - - QProcess *myProcess = new QProcess; - QStringList commandsList; - commandsList << "-c"<setWorkingDirectory(QApplication::applicationDirPath()); - #if !defined(_WIN32)&&(defined(__unix__)||defined(__unix)||(defined(__APPLE__)&&defined(__MACH__))) - myProcess->start("./structrock",commandsList); - #elif defined(_WIN32)||defined(_WIN64) - myProcess->start("structrock",commandsList); - #endif + else + { + Show_Errors(QString("ShowSFeature: No parameters given.")); + } } - TimingShutdown *shutdown(new TimingShutdown); - connect(shutdown, SIGNAL(shutdown()), this, SLOT(exit())); - shutdown->start(); - } - else if(command_string == "showstereonet") - { - if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + else if(command_string == "quitsession") { - std::string filename = dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]; - dataLibrary::current_workline_index+=1; - need_move_on = false; - Stereonet(QString::fromUtf8(filename.c_str())); + if(dataLibrary::current_workline_index+10) + { + commands += dataLibrary::Workflow[i].command; + commands += ","; + for(int j=0; jsetWorkingDirectory(QApplication::applicationDirPath()); + #if !defined(_WIN32)&&(defined(__unix__)||defined(__unix)||(defined(__APPLE__)&&defined(__MACH__))) + myProcess->start("./structrock",commandsList); + #elif defined(_WIN32)||defined(_WIN64) + myProcess->start("structrock",commandsList); + #endif + } + TimingShutdown *shutdown(new TimingShutdown); + connect(shutdown, SIGNAL(shutdown()), this, SLOT(exit())); + shutdown->start(); + } + else if(command_string == "showstereonet") + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + std::string filename = dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0]; + dataLibrary::current_workline_index+=1; + need_move_on = false; + Stereonet(QString::fromUtf8(filename.c_str())); + } + else + { + dataLibrary::current_workline_index+=1; + need_move_on = false; + Stereonet(); + } + } + else if(command_string == "test") + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>0) + { + testworker.setWorkFlowMode(true); + testworker.setSplitMode(false); + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>1) + { + if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[1] == "split") + { + testworker.setSplitMode(true); + } + } + connect(&testworker, SIGNAL(ReadFileReady(int)), this, SLOT(ShowPCD(int))); + connect(&testworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&testworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + connect(&testworker, SIGNAL(GoWorkFlow()), this, SLOT(command_parser())); + + testworker.testing(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str())); + } + else + { + Show_Errors(QString("Test: Path not provided.")); + } } else + { + std::stringstream ss; + ss<addPointCloud(dataLibrary::cloudxyz, dataLibrary::cloudID, v1); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, dataLibrary::cloudID, v1); - pcl::PointXYZ minPt, maxPt; - pcl::getMinMax3D (*dataLibrary::cloudxyz, minPt, maxPt); - float c_x, c_y, c_z; - c_x = (minPt.x+maxPt.x)/2; - c_y = (minPt.y+maxPt.y)/2; - c_z = (minPt.z+maxPt.z)/2; - viewer->setCameraPosition(c_x, c_y, c_z, 0, 0, 0); + viewer->resetCameraViewpoint (dataLibrary::cloudID); + // Position, Viewpoint, Down + viewer->setCameraPose (0,0,0,0,0,-1,0,1,0); viewer->resetCamera(); ui.qvtkWidget->update(); } @@ -906,13 +1320,21 @@ void structrock::ShowPCD(int i) { viewer->addPointCloud(dataLibrary::cloudxyzrgb, dataLibrary::cloudID, v1); - pcl::PointXYZ minPt, maxPt; - pcl::getMinMax3D (*dataLibrary::cloudxyz, minPt, maxPt); - float c_x, c_y, c_z; - c_x = (minPt.x+maxPt.x)/2; - c_y = (minPt.y+maxPt.y)/2; - c_z = (minPt.z+maxPt.z)/2; - viewer->setCameraPosition(c_x, c_y, c_z, 0, 0, 0); + viewer->resetCameraViewpoint (dataLibrary::cloudID); + // Position, Viewpoint, Down + viewer->setCameraPose (0,0,0,0,0,-1,0,1,0); + viewer->resetCamera(); + + ui.qvtkWidget->update(); + } + else if(i==CLOUDXYZI) + { + pcl::visualization::PointCloudColorHandlerGenericField intensity_distribution(dataLibrary::cloudxyzi, "intensity"); + viewer->addPointCloud (dataLibrary::cloudxyzi, intensity_distribution, dataLibrary::cloudID, v1); + + viewer->resetCameraViewpoint (dataLibrary::cloudID); + // Position, Viewpoint, Down + viewer->setCameraPose (0,0,0,0,0,-1,0,1,0); viewer->resetCamera(); ui.qvtkWidget->update(); @@ -947,6 +1369,11 @@ void structrock::saveasbinary() void structrock::exit() { + //begin kinect v2 + if (grabber && grabber->isRunning ()) grabber->stop (); + //end kinect v2 + + cout << '\a'; QApplication::closeAllWindows(); qApp->exit(); } @@ -960,6 +1387,7 @@ void structrock::resampling() if(ok) { resampleworker.setWorkFlowMode(false); + resampleworker.setUnmute(); connect(&resampleworker, SIGNAL(show()), this, SLOT(ShowResample())); connect(&resampleworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&resampleworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -983,10 +1411,6 @@ void structrock::ShowResample() viewer->addPointCloud(dataLibrary::mls_points, "resampled", v2); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, "resampled", v2); ui.qvtkWidget->update(); - - dataLibrary::temp_cloud->clear(); - *dataLibrary::temp_cloud = *dataLibrary::mls_points; - dataLibrary::mls_points->clear(); } void structrock::downsampling() @@ -998,6 +1422,7 @@ void structrock::downsampling() if(ok) { downsampleworker.setWorkFlowMode(false); + downsampleworker.setUnmute(); connect(&downsampleworker, SIGNAL(show()), this, SLOT(ShowDownsample())); connect(&downsampleworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&downsampleworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -1021,10 +1446,6 @@ void structrock::ShowDownsample() viewer->addPointCloud(dataLibrary::downsampledxyz, "downsampled", v2); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, "downsampled", v2); ui.qvtkWidget->update(); - - dataLibrary::temp_cloud->clear(); - *dataLibrary::temp_cloud = *dataLibrary::downsampledxyz; - dataLibrary::downsampledxyz->clear(); } void structrock::k_neighbor() @@ -1036,6 +1457,7 @@ void structrock::k_neighbor() if(ok) { knnormalworker.setWorkFlowMode(false); + knnormalworker.setUnmute(); connect(&knnormalworker, SIGNAL(show()), this, SLOT(ShowknNormal())); connect(&knnormalworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&knnormalworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -1049,19 +1471,26 @@ void structrock::k_neighbor() } } -void structrock::ShowknNormal() +void structrock::ShowknNormal(bool showCurvature) { - viewer->removeAllPointClouds(v1); - viewer->addPointCloud(dataLibrary::cloudxyz, dataLibrary::cloudID, v1); - viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, dataLibrary::cloudID, v1); + if(!showCurvature) + { + viewer->removeAllPointClouds(v1); + viewer->addPointCloud(dataLibrary::cloudxyz, dataLibrary::cloudID, v1); + viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, dataLibrary::cloudID, v1); + } + else + { + viewer->removeAllPointClouds(v1); + pcl::visualization::PointCloudColorHandlerGenericField handler_k(dataLibrary::pointnormals, "curvature"); + viewer->addPointCloud(dataLibrary::pointnormals, handler_k, "curvature", v1); + } viewer->removeAllPointClouds(v2); viewer->addPointCloudNormals(dataLibrary::cloudxyz, dataLibrary::normal, 50, 0.02, "normals", v2); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.0, 1.0, "normals", v2); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 2, "normals", v2); ui.qvtkWidget->update(); - - pcl::concatenateFields(*dataLibrary::cloudxyz, *dataLibrary::normal, *dataLibrary::pointnormals); } void structrock::radius() @@ -1073,6 +1502,7 @@ void structrock::radius() if(ok) { ranormalworker.setWorkFlowMode(false); + ranormalworker.setUnmute(); connect(&ranormalworker, SIGNAL(show()), this, SLOT(ShowraNormal())); connect(&ranormalworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&ranormalworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -1086,19 +1516,26 @@ void structrock::radius() } } -void structrock::ShowraNormal() +void structrock::ShowraNormal(bool showCurvature) { - viewer->removeAllPointClouds(v1); - viewer->addPointCloud(dataLibrary::cloudxyz, dataLibrary::cloudID, v1); - viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, dataLibrary::cloudID, v1); + if(!showCurvature) + { + viewer->removeAllPointClouds(v1); + viewer->addPointCloud(dataLibrary::cloudxyz, dataLibrary::cloudID, v1); + viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, dataLibrary::cloudID, v1); + } + else + { + viewer->removeAllPointClouds(v1); + pcl::visualization::PointCloudColorHandlerGenericField handler_k(dataLibrary::pointnormals, "curvature"); + viewer->addPointCloud(dataLibrary::pointnormals, handler_k, "curvature", v1); + } viewer->removeAllPointClouds(v2); viewer->addPointCloudNormals(dataLibrary::cloudxyz, dataLibrary::normal, 50, 0.02, "normals", v2); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.0, 1.0, "normals", v2); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 2, "normals", v2); ui.qvtkWidget->update(); - - pcl::concatenateFields(*dataLibrary::cloudxyz, *dataLibrary::normal, *dataLibrary::pointnormals); } void structrock::saveScreen() @@ -1123,6 +1560,7 @@ void structrock::StaticRemoveOutlier() if(ok) { staticroworker.setWorkFlowMode(false); + staticroworker.setUnmute(); connect(&staticroworker, SIGNAL(show()), this, SLOT(ShowSRO())); connect(&staticroworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&staticroworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -1153,11 +1591,6 @@ void structrock::ShowSRO() viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, "inlier", v2); ui.qvtkWidget->update(); - - dataLibrary::temp_cloud->clear(); - *dataLibrary::temp_cloud = *dataLibrary::outlier_removed_inlier; - dataLibrary::outlier_removed_inlier->clear(); - dataLibrary::outlier_removed_outlier->clear(); } void structrock::ConditionalRemoveOutlier() @@ -1205,6 +1638,7 @@ void structrock::RegionGrowingSegmentation() dataLibrary::RGSparameter.IsSmoothMode = multi_input.IsSmoothMode(); rgsworker.setWorkFlowMode(false); + rgsworker.setUnmute(); connect(&rgsworker, SIGNAL(show()), this, SLOT(ShowRGS())); connect(&rgsworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&rgsworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -1279,6 +1713,7 @@ void structrock::SaveClusters() if(!filename.isNull()) { saveclustersworker.setWorkFlowMode(false); + saveclustersworker.setUnmute(); connect(&saveclustersworker, SIGNAL(SaveClustersReady(QString)), this, SLOT(ShowSavedClusters(QString))); connect(&saveclustersworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); connect(&saveclustersworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); @@ -1550,6 +1985,27 @@ void structrock::Show_Process() ui.qvtkWidget->update(); } +void structrock::Show_SFeature() +{ + if(!dataLibrary::cloudxyzrgb->empty()) + { + viewer->removeAllPointClouds(v1); + viewer->addPointCloud(dataLibrary::cloudxyzrgb, dataLibrary::cloudID, v1); + } + else + { + viewer->removeAllPointClouds(v1); + viewer->addPointCloud(dataLibrary::cloudxyz, dataLibrary::cloudID, v1); + viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.7, 0.0, dataLibrary::cloudID, v1); + } + + viewer->removeAllPointClouds(v2); + viewer->removeAllShapes(v2); + viewer->addPointCloud(dataLibrary::cloudxyzrgb_features, "feature", v2); + + ui.qvtkWidget->update(); +} + void structrock::OpenClusters() { QString filename = QFileDialog::getOpenFileName(this,tr("Open Point Cloud Clusters Data"),QDir::currentPath(),tr("(*.bin)")); @@ -2047,77 +2503,71 @@ void structrock::Stereonet(QString filename) void structrock::Testing() { - /*if(dataLibrary::Lines.size() == 0) - { - Show_Errors(QString("You Haven't Saved Any Segmentation Yet!")); - } - else + // Function: transform downloaded original ASCII text point cloud file to XYZ file. + /*QString filename = QFileDialog::getOpenFileName(NULL,tr("Open Data File"),QDir::currentPath(),tr("Data (*.txt);;All files (*.*)")); + if(!filename.isNull()) { - QString filename = QFileDialog::getSaveFileName(this,tr("Export Clusters"),QDir::currentPath(),tr("(*.txt)")); - - if(!filename.isNull()) - { - QByteArray ba = filename.toLocal8Bit(); - string* strfilename = new string(ba.data()); - - string patchhullfilename = strfilename->substr(0, strfilename->size()-4) += "_patchhulls.txt"; - ofstream patchhullfout(patchhullfilename.c_str()); + testworker.setWorkFlowMode(false); + connect(&testworker, SIGNAL(showErrors(QString)), this, SLOT(Show_Errors(QString))); + connect(&testworker, SIGNAL(showReadyStatus()), this, SLOT(ShowReady())); + + testworker.testing(filename); + }*/ - int num_of_clusters = dataLibrary::selectedPatches.size(); - patchhullfout<::Ptr plane_cloud (new pcl::PointCloud); - for(int j = 0; j < dataLibrary::clusters[dataLibrary::selectedPatches[cluster_index]].indices.size(); j++) + const char *conninfo; + PGconn *conn; + PGresult *res; + int nFields; + int i, j; + + conninfo = conn_string.toStdString().c_str(); + + /* Make a connection to the database */ + conn = PQconnectdb(conninfo); + + /* Check to see that the backend connection was successfully made */ + if (PQstatus(conn) != CONNECTION_OK) { - plane_cloud->push_back(dataLibrary::cloudxyz->at(dataLibrary::clusters[dataLibrary::selectedPatches[cluster_index]].indices[j])); + std::string Error_message("Connection to database failed: "); + std::ostringstream oss; + oss << PQerrorMessage(conn); + Error_message += oss.str(); + Show_Errors(QString::fromUtf8(Error_message.c_str())); } - - //prepare for projecting data onto plane - float nx, ny, nz; - float curvature; - Eigen::Matrix3f convariance_matrix; - Eigen::Vector4f xyz_centroid, plane_parameters; - pcl::compute3DCentroid(*plane_cloud, xyz_centroid); - pcl::computeCovarianceMatrix(*plane_cloud, xyz_centroid, convariance_matrix); - pcl::solvePlaneParameters(convariance_matrix, nx, ny, nz, curvature); - Eigen::Vector3f centroid; - centroid(0)=xyz_centroid(0); - centroid(1)=xyz_centroid(1); - centroid(2)=xyz_centroid(2); - - //project data onto plane - //set plane parameter - pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients()); - coefficients->values.resize(4); - coefficients->values[0] = nx; - coefficients->values[1] = ny; - coefficients->values[2] = nz; - coefficients->values[3] = - (nx*xyz_centroid[0] + ny*xyz_centroid[1] + nz*xyz_centroid[2]); - //projecting - pcl::PointCloud::Ptr cloud_projected (new pcl::PointCloud); - pcl::ProjectInliers proj; - proj.setModelType(pcl::SACMODEL_PLANE); - proj.setInputCloud(plane_cloud); - proj.setModelCoefficients(coefficients); - proj.filter(*cloud_projected); - - //generate a concave or convex - pcl::PointCloud::Ptr cloud_hull (new pcl::PointCloud); - pcl::ConvexHull chull; - chull.setInputCloud(cloud_projected); - chull.reconstruct(*cloud_hull); - - patchhullfout<size()<<"\n"; - for(int i=0; isize(); i++) - { - patchhullfout<at(i).x<<"\t"<at(i).y<<"\t"<at(i).z<<"\n"; - } - } + else + { + /* + * Our test case here involves using a cursor, for which we must be inside + * a transaction block. We could do the whole thing with a single + * PQexec() of "select * from pg_database", but that's too trivial to make + * a good example. + */ + + /* Start a transaction block */ + res = PQexec(conn, "BEGIN"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + std::string Error_message("BEGIN command failed: "); + std::ostringstream oss; + oss << PQerrorMessage(conn); + Error_message += oss.str(); + Show_Errors(QString::fromUtf8(Error_message.c_str())); + PQclear(res); + } - delete strfilename; - } - }*/ + /* end the transaction */ + res = PQexec(conn, "END"); + PQclear(res); + + /* close the connection to the database and cleanup */ + PQfinish(conn); + } + } } void structrock::TestResult(int i) @@ -2268,6 +2718,22 @@ void structrock::ShowStatus(int i) ui.label->setPalette(pa); break; } + case STATUS_SHOWSFEATURE: + { + head="Busy preparing to show surface features"; + head+=tail; + ui.label->setText(QString::fromStdString(head)); + ui.label->setPalette(pa); + break; + } + case STATUS_TESTING: + { + head="Busy testing"; + head+=tail; + ui.label->setText(QString::fromStdString(head)); + ui.label->setPalette(pa); + break; + } default:{break;} } } diff --git a/structrock.h b/structrock.h index 0722926..ec3a46d 100755 --- a/structrock.h +++ b/structrock.h @@ -50,6 +50,12 @@ #include #include #include +//begin kinect v2 +#include +#include +#include +#include "KinectV2Viewer.h" +//end kinect v2 #include "ReadFileWorker.h" #include "checkstatusThread.h" #include "resampleWorker.h" @@ -70,6 +76,8 @@ #include "SavePcdBinaryWorker.h" #include "SaveNormalsWorker.h" #include "ShowProcessWorker.h" +#include "ShowSFeatureWorker.h" +#include "TestWorker.h" #include "TimingShutdown.h" class structrock : public QMainWindow @@ -92,9 +100,9 @@ private slots: void resampling(); void ShowResample(); void k_neighbor(); - void ShowknNormal(); + void ShowknNormal(bool showCurvature); void radius(); - void ShowraNormal(); + void ShowraNormal(bool showCurvature); void StaticRemoveOutlier(); void ShowSRO(); void ConditionalRemoveOutlier(); @@ -119,6 +127,11 @@ private slots: void command_parser(); void Show_Errors(const QString &errors); void Show_Process(); + void Show_SFeature(); + //begin kinect v2 + void Connect_Kinect(); + void Disconnect_Kinect(); + //end kinect v2 void slotReboot() { QProcess *myProcess = new QProcess; @@ -168,9 +181,17 @@ private slots: QAction *stereonet; QAction *Reboot; QAction *newWindow; + //begin kinect v2 + QAction *connect_Kinect; + QAction *disconnect_Kinect; + //end kinect v2 public: - boost::shared_ptr viewer; + pcl::visualization::PCLVisualizer *viewer; + //begin kinect v2 + pcl::visualization::ImageViewer *image_viewer; + vtkImageViewer2 *imageViewer; + //end kinect v2 int v1; int v2; @@ -193,6 +214,11 @@ private slots: SavePcdBinaryWorker savepcdBinaryworker; SaveNormalsWorker savenormalsworker; ShowProcessWorker showprocessworker; + ShowSFeatureWorker showsfeatureworker; + TestWorker testworker; + //begin kinect v2 + pcl::Grabber *grabber; + //end kinect v2 public: void MoveForwardPatch(); diff --git a/wiki/img/detailed_results.jpg b/wiki/img/detailed_results.jpg new file mode 100644 index 0000000..8f128b1 Binary files /dev/null and b/wiki/img/detailed_results.jpg differ diff --git a/wiki/img/gui.jpg b/wiki/img/gui.jpg new file mode 100644 index 0000000..689d953 Binary files /dev/null and b/wiki/img/gui.jpg differ diff --git a/wiki/img/outcrop_results.jpg b/wiki/img/outcrop_results.jpg new file mode 100644 index 0000000..9b511fd Binary files /dev/null and b/wiki/img/outcrop_results.jpg differ