File indexing completed on 2024-09-22 04:08:42
0001 /* 0002 * SPDX-FileCopyrightText: 2022 Deif Lou <ginoba@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KISSPRAYRANDOMDISTRIBUTIONS_H 0008 #define KISSPRAYRANDOMDISTRIBUTIONS_H 0009 0010 #include <QScopedPointer> 0011 0012 #include <kis_random_source.h> 0013 #include <kis_cubic_curve.h> 0014 0015 /** 0016 * @brief Class that can generate randomly distributed values in the range 0017 * [a..b] following an arbitrary pdf 0018 */ 0019 class KisSprayFunctionBasedDistribution 0020 { 0021 public: 0022 /** 0023 * @brief Construct an invalid KisSprayFunctionBasedDistribution 0024 */ 0025 KisSprayFunctionBasedDistribution(); 0026 0027 /** 0028 * @brief Construct a new distribution 0029 * @tparam Function Type of the functor to sample from 0030 * @param numberOfSamples Number of points to sample from the function. They 0031 * are sampled evenly through the range [a..b]. 0032 * The first point will be sampled at @p a and the 0033 * last one at @p b. 0034 * @param a The lower bound of the domain of the function. The sampling will 0035 * start here 0036 * @param b The upper bound of the domain of the function. The sampling will 0037 * start here 0038 * @param f The functor that will be used to get the samples 0039 */ 0040 template <typename Function> 0041 KisSprayFunctionBasedDistribution(int numberOfSamples, double a, double b, Function f); 0042 0043 ~KisSprayFunctionBasedDistribution(); 0044 KisSprayFunctionBasedDistribution(const KisSprayFunctionBasedDistribution &other); 0045 KisSprayFunctionBasedDistribution& operator=(const KisSprayFunctionBasedDistribution &rhs); 0046 0047 /** 0048 * @brief Get a random value between @ref min and @ref max that follows the distribution 0049 * @param rs The random source object that will be used to get a uniform value 0050 * @return A random value between @ref min and @ref max that follows the 0051 * distribution 0052 */ 0053 double operator()(KisRandomSourceSP rs) const; 0054 0055 /** 0056 * @brief Return the minimum value that this distribution can produce 0057 */ 0058 double min() const; 0059 0060 /** 0061 * @brief Return the maximum value that this distribution can produce 0062 */ 0063 double max() const; 0064 0065 /** 0066 * @brief Return if this object is correctly initialized and can be used to 0067 * generate values 0068 */ 0069 bool isValid() const; 0070 0071 protected: 0072 /** 0073 * @brief Function used to setup the distribution and put it in a valid 0074 * state. See the constructor for the explanation of the parameters 0075 */ 0076 template <typename Function> 0077 void initialize(size_t numberOfSamples, double a, double b, Function f); 0078 0079 private: 0080 class Private; 0081 QScopedPointer<Private> m_d; 0082 }; 0083 0084 /** 0085 * @brief Class that can generate uniformly distributed values in 0086 * the [0..1) range 0087 */ 0088 class KisSprayUniformDistribution 0089 { 0090 public: 0091 /** 0092 * @brief Get a random value between @ref min and @ref max that follows a uniform distribution 0093 * @param rs The random source object that will be used to get a uniform value 0094 * @return A random value between @ref min and @ref max that follows the 0095 * distribution 0096 */ 0097 double operator()(KisRandomSourceSP rs) const; 0098 0099 /** 0100 * @brief Return the minimum value that this distribution can produce 0101 */ 0102 double min() const { return 0.0; } 0103 0104 /** 0105 * @brief Return the maximum value that this distribution can produce 0106 */ 0107 double max() const { return 1.0; } 0108 0109 /** 0110 * @brief Return if this object is correctly initialized and can be used to 0111 * generate values 0112 */ 0113 bool isValid() const { return true; } 0114 }; 0115 0116 /** 0117 * @brief Class that can generate uniformly distributed values in 0118 * the [0..1) range, for polar coordinates distance 0119 */ 0120 class KisSprayUniformDistributionPolarDistance : public KisSprayUniformDistribution 0121 { 0122 public: 0123 double operator()(KisRandomSourceSP rs) const; 0124 }; 0125 0126 /** 0127 * @brief Class that can generate normally distributed values. For efficiency, 0128 * the values will be in the range [0..standardDeviation*5] 0129 */ 0130 class KisSprayNormalDistribution : public KisSprayFunctionBasedDistribution 0131 { 0132 public: 0133 /** 0134 * @brief Construct an invalid KisSprayNormalDistribution 0135 */ 0136 KisSprayNormalDistribution(); 0137 0138 /** 0139 * @brief Construct a new normal distribution 0140 * @param mean Where the "peak" of the distribution should lie or how much 0141 * the distribution is shifted left or right 0142 * @param standardDeviation How spread should the distribution be 0143 */ 0144 KisSprayNormalDistribution(double mean, double standardDeviation); 0145 }; 0146 0147 /** 0148 * @brief Class that can generate normally distributed values. For efficiency, 0149 * the values will be in the range [0..standardDeviation*5], for polar 0150 * coordinates distance 0151 * @see KisSprayNormalDistribution 0152 */ 0153 class KisSprayNormalDistributionPolarDistance : public KisSprayNormalDistribution 0154 { 0155 public: 0156 KisSprayNormalDistributionPolarDistance(); 0157 KisSprayNormalDistributionPolarDistance(double mean, double standardDeviation); 0158 }; 0159 0160 /** 0161 * @brief Class that can generate randomly distributed values in the range 0162 * [0..1] that follow a distribution that clusters the values 0163 * towards 0 or 1 0164 */ 0165 class KisSprayClusterBasedDistribution : public KisSprayFunctionBasedDistribution 0166 { 0167 public: 0168 /** 0169 * @brief Construct an invalid KisSprayClusterBasedDistribution 0170 */ 0171 KisSprayClusterBasedDistribution(); 0172 0173 /** 0174 * @brief Construct a new cluster based distribution 0175 * @param clusteringAmount A value in the range [-100..100] that indicates 0176 * how and how much the generated values should 0177 * cluster. A positive clustering amount will make 0178 * generated values cluster towards 0 whereas a 0179 * negative amount will cluster them towards 1. The 0180 * bigger the clustering amount, the more pronounced 0181 * will be the clustering, and the smaller it is, 0182 * the more evenly distributed the values will be 0183 */ 0184 explicit KisSprayClusterBasedDistribution(double clusteringAmount); 0185 }; 0186 0187 /** 0188 * @brief Class that can generate randomly distributed values in the range 0189 * [0..1] that follow a distribution that clusters the values 0190 * towards 0 or 1, for polar coordinates distance 0191 * @see KisSprayClusterBasedDistribution 0192 */ 0193 class KisSprayClusterBasedDistributionPolarDistance : public KisSprayFunctionBasedDistribution 0194 { 0195 public: 0196 KisSprayClusterBasedDistributionPolarDistance(); 0197 explicit KisSprayClusterBasedDistributionPolarDistance(double clusteringAmount); 0198 }; 0199 0200 /** 0201 * @brief Class that can generate randomly distributed values in the range 0202 * [0..1] that follow a distribution given by a user defined cubic curve 0203 */ 0204 class KisSprayCurveBasedDistribution : public KisSprayFunctionBasedDistribution 0205 { 0206 public: 0207 /** 0208 * @brief Construct an invalid KisSprayCurveBasedDistribution 0209 */ 0210 KisSprayCurveBasedDistribution(); 0211 0212 /** 0213 * @brief Construct a new curve based distribution 0214 * @param curve A cubic curve that will be used as pdf 0215 * @param repeat The number of times the given curve should repeat in the 0216 * range [0..1] 0217 */ 0218 explicit KisSprayCurveBasedDistribution(const KisCubicCurve &curve, size_t repeat = 1); 0219 }; 0220 0221 /** 0222 * @brief Class that can generate randomly distributed values in the range 0223 * [0..1] that follow a distribution given by a user defined cubic curve, 0224 * for polar coordinates distance 0225 * @see KisSprayCurveBasedDistribution 0226 */ 0227 class KisSprayCurveBasedDistributionPolarDistance : public KisSprayFunctionBasedDistribution 0228 { 0229 public: 0230 KisSprayCurveBasedDistributionPolarDistance(); 0231 explicit KisSprayCurveBasedDistributionPolarDistance(const KisCubicCurve &curve, size_t repeat = 1); 0232 }; 0233 0234 #endif