RoboDK Plug-In Interface
Loading...
Searching...
No Matches
legacymatrix2d.cpp
1/****************************************************************************
2**
3** Copyright (c) 2015-2025 RoboDK Inc.
4** Contact: https://robodk.com/
5**
6** This file is part of the RoboDK API.
7**
8** Permission is hereby granted, free of charge, to any person obtaining a copy
9** of this software and associated documentation files (the "Software"), to deal
10** in the Software without restriction, including without limitation the rights
11** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12** copies of the Software, and to permit persons to whom the Software is
13** furnished to do so, subject to the following conditions:
14**
15** The above copyright notice and this permission notice shall be included in all
16** copies or substantial portions of the Software.
17**
18** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24** SOFTWARE.
25**
26** RoboDK is a registered trademark of RoboDK Inc.
27**
28****************************************************************************/
29
30#include "legacymatrix2d.h"
31
32#include <cstdlib>
33
34#ifdef QT_GUI_LIB
35#include <QTextStream>
36#include <QDataStream>
37#include <QDebug>
38#endif // QT_GUI_LIB
39
40
41namespace robodk
42{
43
44namespace legacy
45{
46
47static void emxInit_real_T(Matrix2D** pMatrix, int dimensions)
48{
49 if (!pMatrix)
50 return;
51
52 if (dimensions < 0)
53 {
54 *pMatrix = nullptr;
55 return;
56 }
57
58 *pMatrix = (Matrix2D*) malloc(sizeof(Matrix2D));
59 Matrix2D* matrix = *pMatrix;
60 if (!matrix)
61 return;
62
63 matrix->data = nullptr;
64 matrix->numDimensions = dimensions;
65 matrix->size = (int*) malloc(sizeof(int) * dimensions);
66 matrix->allocatedSize = 0;
67 matrix->canFreeData = true;
68
69 for (int i = 0; i < dimensions; i++)
70 matrix->size[i] = 0;
71}
72
73static void emxFree_real_T(Matrix2D** pMatrix)
74{
75 if (!pMatrix)
76 return;
77
78 auto matrix = *pMatrix;
79 if (!matrix)
80 return;
81
82 if (matrix->canFreeData)
83 free(matrix->data);
84
85 free(matrix->size);
86 free(matrix);
87
88 *pMatrix = nullptr;
89}
90
91static void emxEnsureCapacity(Matrix2D* matrix, int oldNumel, size_t elementSize)
92{
93 if (!matrix)
94 return;
95
96 double *newData;
97
98 if (oldNumel < 0)
99 oldNumel = 0;
100
101 int newNumel = 1;
102 for (int i = 0; i < matrix->numDimensions; i++)
103 newNumel *= matrix->size[i];
104
105 if (newNumel <= matrix->allocatedSize)
106 return;
107
108 int newSize = matrix->allocatedSize;
109 if (newSize < 16)
110 newSize = 16;
111
112 while (newSize < newNumel)
113 {
114 if (newSize > 1073741823)
115 {
116 newSize = 2147483647; //MAX_int32_T;
117 }
118 else
119 {
120 newSize <<= 1;
121 }
122 }
123
124 newData = (double*) calloc(newSize, elementSize);
125 if (matrix->data)
126 {
127 memcpy(newData, matrix->data, elementSize * oldNumel);
128 if (matrix->canFreeData)
129 free(matrix->data);
130 }
131
132 matrix->data = newData;
133 matrix->allocatedSize = newSize;
134 matrix->canFreeData = true;
135}
136
137Matrix2D* Matrix2D_Create()
138{
139 Matrix2D* matrix;
140 emxInit_real_T(&matrix, 2);
141 return matrix;
142}
143
144void Matrix2D_Delete(Matrix2D** matrix)
145{
146 emxFree_real_T(matrix);
147}
148
149void Matrix2D_SetDimensions(Matrix2D* matrix, int rows, int columns)
150{
151 int size = matrix->size[0] * matrix->size[1];
152 matrix->size[0] = rows;
153 matrix->size[1] = columns;
154 emxEnsureCapacity(matrix, size, sizeof(double));
155}
156
157int Matrix2D_GetDimension(const Matrix2D* matrix, int dimension)
158{
159 // ONE BASED!!
160 if (matrix->numDimensions >= dimension)
161 {
162 return matrix->size[dimension - 1];
163 }
164 else
165 {
166 return 0;
167 }
168}
169
170int Matrix2D_ColumnCount(const Matrix2D* matrix)
171{
172 return Matrix2D_GetDimension(matrix, 2);
173}
174
175int Matrix2D_RowCount(const Matrix2D* matrix)
176{
177 return Matrix2D_GetDimension(matrix, 1);
178}
179
180double Matrix2D_Get(const Matrix2D* matrix, int row, int column)
181{
182 // ZERO BASED!!
183 return matrix->data[matrix->size[0] * column + row];
184}
185
186void Matrix2D_Set(const Matrix2D* matrix, int row, int column, double value)
187{
188 // ZERO BASED!!
189 matrix->data[matrix->size[0] * column + row] = value;
190}
191
192double* Matrix2D_GetColumn(const Matrix2D* matrix, int column)
193{
194 // ZERO BASED!!
195 return (matrix->data + matrix->size[0] * column);
196}
197
198bool Matrix2D_Copy(const Matrix2D* source, Matrix2D* destination)
199{
200 if (source->numDimensions != 2 || destination->numDimensions != 2)
201 {
202 Matrix2D_SetDimensions(destination, 0, 0);
203 return false;
204 }
205
206 int sz1 = Matrix2D_GetDimension(source, 1);
207 int sz2 = Matrix2D_GetDimension(source, 2);
208 Matrix2D_SetDimensions(destination, sz1, sz2);
209 int numel = sz1 * sz2;
210 for (int i = 0; i < numel; i++)
211 {
212 destination->data[i] = source->data[i];
213 }
214
215 return true;
216}
217
218#ifdef QT_GUI_LIB
219void Matrix2D_DebugArray(const double *array, int size)
220{
221 int i;
222 QString strout;
223 for (i = 0; i < size; i++) {
224 strout.append(QString::number(array[i], 'f', 3));
225 if (i < size - 1) {
226 strout.append(" , ");
227 }
228 }
229 qDebug().noquote() << strout;
230}
231
232void Matrix2D_Debug(const Matrix2D* matrix)
233{
234 int size1;
235 int size2;
236 int j;
237 double *column;
238 size1 = Matrix2D_RowCount(matrix);
239 size2 = Matrix2D_ColumnCount(matrix);
240 qDebug().noquote() << "Matrix size = " << size1 << " x " << size2;
241 if (size1*size2 == 0)
242 {
243 return;
244 }
245 for (j = 0; j<size2; j++)
246 {
247 column = Matrix2D_GetColumn(matrix, j);
248 Matrix2D_DebugArray(column, size1);
249 }
250}
251
252void Matrix2D_Save(QTextStream *stream, Matrix2D* matrix, bool csv)
253{
254 int size1;
255 int size2;
256 int j;
257 double *column;
258 size1 = Matrix2D_RowCount(matrix);
259 size2 = Matrix2D_ColumnCount(matrix);
260 //*st << "% Matrix size = " << size1 << " x " << size2;
261 if (size1 * size2 == 0)
262 {
263 return;
264 }
265
266 if (csv)
267 {
268 for (j = 0; j<size2; j++)
269 {
270 column = Matrix2D_GetColumn(matrix, j);
271 for (int i = 0; i < size1; i++)
272 {
273 *stream << QString::number(column[i], 'f', 8) << ", ";
274 }
275 *stream << "\n";
276 }
277 }
278 else
279 {
280 for (j = 0; j<size2; j++)
281 {
282 column = Matrix2D_GetColumn(matrix, j);
283 *stream << "[";
284 for (int i = 0; i < size1; i++)
285 {
286 *stream << QString::number(column[i], 'f', 8) << " ";
287 }
288 *stream << "];\n";
289 }
290 }
291}
292
293void Matrix2D_Save(QDataStream* stream, Matrix2D* matrix)
294{
295 int i;
296 *stream << matrix->numDimensions;
297 int size_values = 1;
298 for (i = 0; i < matrix->numDimensions; i++)
299 {
300 qint32 sizei = matrix->size[i];
301 size_values = size_values * sizei;
302 *stream << sizei;
303 }
304 for (i = 0; i < size_values; i++)
305 {
306 *stream << matrix->data[i];
307 }
308}
309
310void Matrix2D_Load(QDataStream *stream, Matrix2D** matrix)
311{
312 if (stream->atEnd())
313 {
314 qDebug() << "No data to read";
315 return;
316 }
317
318 if (*matrix != nullptr)
319 {
320 Matrix2D_Delete(matrix);
321 }
322
323 int i;
324 qint32 ndim;
325 qint32 sizei;
326 *stream >> ndim;
327 qDebug() << "Loading matrix of dimensions: " << ndim;
328 emxInit_real_T(matrix, ndim);
329 int size_values = 1;
330 for (i = 0; i < ndim; i++)
331 {
332 *stream >> sizei;
333 size_values = size_values * sizei;
334 (*matrix)->size[i] = sizei;
335 }
336 //emxEnsureCapacity((emxArray__common *) *emx, 0, (int32_T)sizeof(real_T));
337 emxEnsureCapacity(*matrix, 0, sizeof(double));
338 double value;
339 for (i = 0; i < size_values; i++)
340 {
341 *stream >> value;
342 (*matrix)->data[i] = value;
343 }
344}
345#endif // QT_GUI_LIB
346
347
348} // namespace legacy
349
350} // namespace robodk