#ifndef SHEET_H #define SHEET_H #include #include #include class QImage; /// Temperatures are stores into a matrix of double values typedef QVector< QVector > TemperatureMatrix; /// A rectangular sheet where heat is simulated class Sheet : public QObject { Q_OBJECT Q_DISABLE_COPY(Sheet) protected: /// A sheet is a matrix of temperatures TemperatureMatrix temperatures1; /// But two marixes are used to simulate the generations TemperatureMatrix temperatures2; /// The current updated matrix in the simulation TemperatureMatrix* current = &temperatures1; /// The next generation will be stored in this matrix TemperatureMatrix* next = &temperatures2; /// The minimum temperature loaded from CSV file double minimum = DBL_MAX; /// The maximum temperature loaded from CSV file double maximum = DBL_MIN; /// The epsilon used to detect if no change in the sheet and stop double epsilon = 0.001; /// The current generation simulated unsigned long long generation = 0; /// True if the simulation is in progress bool simulating = false; public: /// Constructor explicit Sheet(QObject* parent = nullptr); /// Get the minimum temperature of the sheet inline double getMinimum() const { return this->minimum; } /// Get the maximum temperature of the sheet inline double getMaximum() const { return this->maximum; } /// Get the epsilon used to stop the simulation when the temperature stabilishes inline double getEpsilon() const { return this->epsilon; } /// Loads a sheet from a CSV or CST file /// @return A sheet pointer if the file is valid, nullptr otherwise static Sheet* load(const QString& filePath, QObject* parent = nullptr); /// Load the temperatures from the csv file /// @return true on success, false on error bool loadCsv(const QString& filePath); /// Load the temperatures from the csv file using the given separator /// @return true on success, false on error bool loadCsv(const QString& filePath, char separator); /// Get the number of rows inline int getRows() const { return this->temperatures1.count(); } /// Get the number of columns inline int getColumns() const { return this->temperatures1.count() > 0 ? this->temperatures1[0].count() : 0; } /// Get the current generation inline unsigned long long getGeneration() const { return this->generation; } /// Get read-only access to the current matrix inline const TemperatureMatrix& getCurrentMatrix() const { return *this->current; } #ifdef HEAT_TRANSMISSION_GUI /// Fills the given image with pixels sampled from the temperatures of this sheet /// @return true on success, false otherwise bool fillImage(QImage& image); #endif /// Start the simulation at full speed of this machine /// @param epsilon The simulation will stop when all cells have a temperature change less than /// this real number. For example 0.000001. It must be greater than 0.0. /// @return true If simulation started, false if epsilon is negative or zero bool startSimulation(double epsilon); /// Stop the simulation void stopSimulation(); signals: /// Emitted when the simulation has finished /// @param generations The number of generations done void simulationDone(unsigned long long generations); protected: /// Load the temperatures from csv line using the given separator /// @return true on success, false on error bool loadLine(const QString& line, char separator); /// Updates the matrixes with the next generation of heat transfer /// @return The maximum heat change detected into a cell double updateGeneration(); /// Updates the temperature of a cell from current matrix to the next one /// as the average of the four neighbors in the four cardinal points /// @return the difference of temperature from old state to the new one double updateCell(int row, int col); }; #endif // SHEET_H