commit 6de64486e2644daa40f663d01623c97aaf760a2f Author: Paul Leroy Date: Wed Nov 22 12:56:31 2023 +0100 initial commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e4852eb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +# CloudCompare example for standard plugins + +# REPLACE ALL 'G3PointPlugin' OCCURENCES BY YOUR PLUGIN NAME +# AND ADAPT THE CODE BELOW TO YOUR OWN NEEDS! + +# Add an option to CMake to control whether we build this plugin or not +option( PLUGIN_G3POINT "Install example plugin" OFF ) + +if ( PLUGIN_G3POINT ) + project( G3PointPlugin ) + + AddPlugin( NAME ${PROJECT_NAME} ) + + add_subdirectory( include ) + add_subdirectory( src ) + + # set dependencies to necessary libraries + # target_link_libraries( ${PROJECT_NAME} LIB1 ) +endif() diff --git a/images/icon.png b/images/icon.png new file mode 100644 index 0000000..2c923cc Binary files /dev/null and b/images/icon.png differ diff --git a/include/ActionA.h b/include/ActionA.h new file mode 100644 index 0000000..af30eaf --- /dev/null +++ b/include/ActionA.h @@ -0,0 +1,11 @@ +// Example of a plugin action + +#pragma once + +class ccMainAppInterface; + +namespace G3Point +{ +void find_neighbors(); +void performActionA( ccMainAppInterface *appInterface ); +} diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..056d1eb --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,11 @@ + +target_sources( ${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/ActionA.h + ${CMAKE_CURRENT_LIST_DIR}/G3PointPlugin.h +) + +target_include_directories( ${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/include/G3PointPlugin.h b/include/G3PointPlugin.h new file mode 100644 index 0000000..170d876 --- /dev/null +++ b/include/G3PointPlugin.h @@ -0,0 +1,65 @@ +//########################################################################## +//# # +//# CLOUDCOMPARE PLUGIN: G3PointPlugin # +//# # +//# This program is free software; you can redistribute it and/or modify # +//# it under the terms of the GNU General Public License as published by # +//# the Free Software Foundation; version 2 of the License. # +//# # +//# This program is distributed in the hope that it will be useful, # +//# but WITHOUT ANY WARRANTY; without even the implied warranty of # +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +//# GNU General Public License for more details. # +//# # +//# COPYRIGHT: XXX # +//# # +//########################################################################## + +#pragma once + +#include "ccStdPluginInterface.h" + +//! Example qCC plugin +/** Replace 'G3PointPlugin' by your own plugin class name throughout and then + check 'G3PointPlugin.cpp' for more directions. + + Each plugin requires an info.json file to provide information about itself - + the name, authors, maintainers, icon, etc.. + + The one method you are required to implement is 'getActions'. This should + return all actions (QAction objects) for the plugin. CloudCompare will + automatically add these with their icons in the plugin toolbar and to the + plugin menu. If your plugin returns several actions, CC will create a + dedicated toolbar and a sub-menu for your plugin. You are responsible for + connecting these actions to methods in your plugin. + + Use the ccStdPluginInterface::m_app variable for access to most of the CC + components (database, 3D views, console, etc.) - see the ccMainAppInterface + class in ccMainAppInterface.h. +**/ +class G3PointPlugin : public QObject, public ccStdPluginInterface +{ + Q_OBJECT + Q_INTERFACES( ccPluginInterface ccStdPluginInterface ) + + // Replace "Example" by your plugin name (IID should be unique - let's hope your plugin name is unique ;) + // The info.json file provides information about the plugin to the loading system and + // it is displayed in the plugin information dialog. + Q_PLUGIN_METADATA( IID "cccorp.cloudcompare.plugin.G3Point" FILE "../info.json" ) + +public: + explicit G3PointPlugin( QObject *parent = nullptr ); + ~G3PointPlugin() override = default; + + // Inherited from ccStdPluginInterface + void onNewSelection( const ccHObject::Container &selectedEntities ) override; + QList getActions() override; + +private: + //! Default action + /** You can add as many actions as you want in a plugin. + Each action will correspond to an icon in the dedicated + toolbar and an entry in the plugin menu. + **/ + QAction* m_action; +}; diff --git a/info.json b/info.json new file mode 100644 index 0000000..8516f1f --- /dev/null +++ b/info.json @@ -0,0 +1,26 @@ +{ + "type" : "Standard", + "name" : "G3Point", + "icon" : ":/CC/plugin/G3PointPlugin/images/icon.png", + "description": "G3Point grain segmentation algorithm.", + "authors" : [ + { + "name" : "Paul Leroy", + "email" : "paul.leroy@univ-rennes.fr" + } + ], + "references" : [ + { + "text" : "Size, shape and orientation matter: fast and automatic measurement of grain geometries from 3D point clouds", + "url" : "https://esurf.copernicus.org/articles/10/1211/2022/" + }, + { + "text" : "G3Point original source repository", + "url" : "https://github.com/philippesteer/G3Point" + }, + { + "text" : "G3Point python source repository", + "url" : "https://github.com/p-leroy/g3point_python" + } + ] +} diff --git a/qG3POINT.qrc b/qG3POINT.qrc new file mode 100644 index 0000000..a4ff951 --- /dev/null +++ b/qG3POINT.qrc @@ -0,0 +1,6 @@ + + + images/icon.png + info.json + + diff --git a/src/ActionA.cpp b/src/ActionA.cpp new file mode 100644 index 0000000..a14d330 --- /dev/null +++ b/src/ActionA.cpp @@ -0,0 +1,42 @@ +#include "ActionA.h" + +#include "ccMainAppInterface.h" +#include "ccPointCloud.h" + +namespace G3Point +{ + + void find_neighbors() +{ + } + + void performActionA( ccMainAppInterface *appInterface ) + { + if ( appInterface == nullptr ) + { + // The application interface should have already been initialized when the plugin is loaded + Q_ASSERT( false ); + + return; + } + + /*** HERE STARTS THE ACTION ***/ + + // Find neighbors of each point of the cloud + + + // Perform initial segmentation + + // This is how you can output messages + // Display a standard message in the console + appInterface->dispToConsole( "[ExamplePlugin] Hello world!", ccMainAppInterface::STD_CONSOLE_MESSAGE ); + + // Display a warning message in the console + appInterface->dispToConsole( "[ExamplePlugin] Warning: example plugin shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE ); + + // Display an error message in the console AND pop-up an error box + appInterface->dispToConsole( "Example plugin shouldn't be used - it doesn't do anything!", ccMainAppInterface::ERR_CONSOLE_MESSAGE ); + + /*** HERE ENDS THE ACTION ***/ + } +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..310a0c1 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,6 @@ + +target_sources( ${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/ActionA.cpp + ${CMAKE_CURRENT_LIST_DIR}/G3PointPlugin.cpp +) diff --git a/src/G3PointPlugin.cpp b/src/G3PointPlugin.cpp new file mode 100644 index 0000000..9709883 --- /dev/null +++ b/src/G3PointPlugin.cpp @@ -0,0 +1,95 @@ +//########################################################################## +//# # +//# CLOUDCOMPARE PLUGIN: G3PointPlugin # +//# # +//# This program is free software; you can redistribute it and/or modify # +//# it under the terms of the GNU General Public License as published by # +//# the Free Software Foundation; version 2 of the License. # +//# # +//# This program is distributed in the hope that it will be useful, # +//# but WITHOUT ANY WARRANTY; without even the implied warranty of # +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +//# GNU General Public License for more details. # +//# # +//# COPYRIGHT: XXX # +//# # +//########################################################################## + +// First: +// Replace all occurrences of 'G3PointPlugin' by your own plugin class name in this file. +// This includes the resource path to info.json in the constructor. + +// Second: +// Open G3PointPlugin.qrc, change the "prefix" and the icon filename for your plugin. +// Change the name of the file to .qrc + +// Third: +// Open the info.json file and fill in the information about the plugin. +// "type" should be one of: "Standard", "GL", or "I/O" (required) +// "name" is the name of the plugin (required) +// "icon" is the Qt resource path to the plugin's icon (from the .qrc file) +// "description" is used as a tootip if the plugin has actions and is displayed in the plugin dialog +// "authors", "maintainers", and "references" show up in the plugin dialog as well + +#include + +#include "G3PointPlugin.h" + +#include "ActionA.h" + +// Default constructor: +// - pass the Qt resource path to the info.json file (from .qrc file) +// - constructor should mainly be used to initialize actions and other members +G3PointPlugin::G3PointPlugin( QObject *parent ) + : QObject( parent ) + , ccStdPluginInterface( ":/CC/plugin/G3PointPlugin/info.json" ) + , m_action( nullptr ) +{ +} + +// This method should enable or disable your plugin actions +// depending on the currently selected entities ('selectedEntities'). +void G3PointPlugin::onNewSelection( const ccHObject::Container &selectedEntities ) +{ + if ( m_action == nullptr ) + { + return; + } + + // If you need to check for a specific type of object, you can use the methods + // in ccHObjectCaster.h or loop and check the objects' classIDs like this: + // + // for ( ccHObject *object : selectedEntities ) + // { + // if ( object->getClassID() == CC_TYPES::VIEWPORT_2D_OBJECT ) + // { + // // ... do something with the viewports + // } + // } + + // For example - only enable our action if something is selected. + m_action->setEnabled( !selectedEntities.empty() ); +} + +// This method returns all the 'actions' your plugin can perform. +// getActions() will be called only once, when plugin is loaded. +QList G3PointPlugin::getActions() +{ + // default action (if it has not been already created, this is the moment to do it) + if ( !m_action ) + { + // Here we use the default plugin name, description, and icon, + // but each action should have its own. + m_action = new QAction( getName(), this ); + m_action->setToolTip( getDescription() ); + m_action->setIcon( getIcon() ); + + // Connect appropriate signal + connect( m_action, &QAction::triggered, this, [this]() + { + Example::performActionA( m_app ); + }); + } + + return { m_action }; +}