File: FeaturesInterface.h

package info (click to toggle)
cloudcompare 2.13.2%2Bgit20240821%2Bds-1
  • links: PTS
  • area: main
  • in suites: trixie
  • size: 151,152 kB
  • sloc: cpp: 687,217; ansic: 165,269; python: 31,109; xml: 25,906; sh: 940; makefile: 509; java: 229; asm: 204; fortran: 160; javascript: 73; perl: 18
file content (248 lines) | stat: -rw-r--r-- 6,925 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#pragma once

//##########################################################################
//#                                                                        #
//#                     CLOUDCOMPARE PLUGIN: q3DMASC                       #
//#                                                                        #
//#  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 or later 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: Dimitri Lague / CNRS / UEB                  #
//#                                                                        #
//##########################################################################


//Local
#include "CorePoints.h"
#include "ScalarFieldCollector.h"
#include "ScalarFieldWrappers.h"

//Qt
#include <QString>

//system
#include <assert.h>

class ccPointCloud;

namespace CCLib
{
	class ScalarField;
};

namespace masc
{
	//! Generic feature descriptor
	struct Feature
	{
	public: //shortcuts

		//!Shared type
		typedef QSharedPointer<Feature> Shared;

		//! Set of features
		typedef std::vector<Shared> Set;

	public: //enumerators

		//! Feature type
		enum class Type
		{
			PointFeature,			/*!< Point features (scalar field, etc.) */
			NeighborhoodFeature,	/*!< Neighborhood based features for a given scale */
			ContextBasedFeature,	/*!< Contextual based features */
			DualCloudFeature,		/*!< Dual Cloud features: requires 2 point clouds */
			Invalid					/*!< Invalid feature */
		};

		enum Stat
		{
			NO_STAT,
			MEAN,
			MODE, //number with the highest frequency
			MEDIAN,
			STD,
			RANGE,
			SKEW //(SKEW = (MEAN - MODE)/STD)
		};

		static QString StatToString(Stat stat)
		{
			switch (stat)
			{
			case MEAN:
				return "MEAN";
			case MODE:
				return "MODE";
			case MEDIAN:
				return "MEDIAN";
			case STD:
				return "STD";
			case RANGE:
				return "RANGE";
			case SKEW:
				return "SKEW";
			default:
				break;
			};
			return QString();
		}

		enum Operation
		{
			NO_OPERATION, MINUS, PLUS, DIVIDE, MULTIPLY
		};

		static QString OpToString(Operation op)
		{
			switch (op)
			{
			case MINUS:
				return "MINUS";
			case PLUS:
				return "PLUS";
			case DIVIDE:
				return "DIVIDE";
			case MULTIPLY:
				return "MULTIPLY";
			default:
				break;
			};
			return QString();
		}

		//! Sources of values for this feature
		struct Source
		{
			using Set = std::vector<Source>;

			//! Sources types
			enum Type
			{
				ScalarField = 0,
				DimX,
				DimY,
				DimZ,
				Red,
				Green,
				Blue
			};

			Source(Type t = ScalarField, QString n = QString())
				: type(t)
				, name(n)
			{}
			
			Type type;
			QString name;
		};

		//! Extracts the set of 'sources' from a set of features
		static bool ExtractSources(const Set& features, Source::Set& sources);

		//! Saves a set of 'sources' to a file
		static bool SaveSources(const Source::Set& sources, QString filename);

		//! Loads a set of 'sources' from a file
		static bool LoadSources(Source::Set& sources, QString filename);

	public: //methods

		//! Default constructor
		Feature(double p_scale = std::numeric_limits<double>::quiet_NaN(), Source::Type p_source = Source::ScalarField, QString p_sourceName = QString())
			: scale(p_scale)
			, cloud1(nullptr)
			, cloud2(nullptr)
			, source(p_source, p_sourceName)
			, stat(NO_STAT)
			, op(NO_OPERATION)
			, sf1WasAlreadyExisting(false)
			, sf2WasAlreadyExisting(false)
		{}

		//! Destructor
		virtual ~Feature() {}

		//! Returns the type (must be reimplemented by child struct)
		virtual Type getType() const = 0;

		//! Returns the formatted description
		virtual QString toString() const = 0;

		//! Clones this feature
		virtual Feature::Shared clone() const = 0;

		//! Prepares the feature (compute the scalar field, etc.)
        virtual bool prepare(const CorePoints& corePoints, QString& error, CCCoreLib::GenericProgressCallback* progressCb = nullptr, SFCollector* generatedScalarFields = nullptr) = 0;

		//! Finishes the feature preparation (update the scalar field, etc.)
		virtual bool finish(const CorePoints& corePoints, QString& error) { /* does nothing by default*/return true; }

		//! Returns whether the feature has an associated scale
		inline bool scaled() const { return std::isfinite(scale); }

		//! Checks the feature definition validity
		virtual bool checkValidity(QString corePointRole, QString &error) const
		{
			unsigned char cloudCount = (cloud1 ? (cloud2 ? 2 : 1) : 0);
			if (cloudCount == 0)
			{
				error = "feature has no associated cloud";
				return false;
			}

			if (stat != NO_STAT && getType() != Type::PointFeature)
			{
				error = "STAT measures can only be defined on Point features";
				return false;
			}

			if (op != NO_OPERATION && cloudCount < 2)
			{
				error = "at least two clouds are required to apply math operations";
				return false;
			}

			return true;
		}

	public: //helpers

		//! Creates (or resets) a scalar field with the given name on the input core points cloud
		static bool CheckSFExistence(ccPointCloud* cloud, const char* resultSFName);

		//! Creates (or resets) a scalar field with the given name on the input core points cloud
		static CCCoreLib::ScalarField* PrepareSF(ccPointCloud* cloud, const char* resultSFName, SFCollector* generatedScalarFields/*= nullptr*/, SFCollector::Behavior behavior);

		//! Performs a mathematical operation between two scalars
		static ScalarType PerformMathOp(double s1, double s2, Operation op);

		//! Performs a mathematical operation between two scalar fields (they must have the same size!)
		static bool PerformMathOp(CCCoreLib::ScalarField* sf1, const CCCoreLib::ScalarField* sf2, Operation op);

		//! Performs a mathematical operation between two scalar fields (they must have the same size!)
		static bool PerformMathOp(const IScalarFieldWrapper& sf1, const IScalarFieldWrapper& sf2, Operation op, CCCoreLib::ScalarField* outSF);

	public: //members

		//! Scale (diameter)
		double scale;

		ccPointCloud *cloud1, *cloud2;
		QString cloud1Label, cloud2Label;
	
		Source source; //values source
	
		Stat stat; //only considered if a scale is defined
		Operation op; //only considered if 2 clouds are defined

		bool sf1WasAlreadyExisting;
		bool sf2WasAlreadyExisting; // only considered if a second scalar field may be necessary (PointFeature, NeighborhoodFeature)
	};
}