RCube
Rcube Rest Server calculates sail routes based on Grib files and sailing boat polar files
Loading...
Searching...
No Matches
polar.c
Go to the documentation of this file.
1
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <stdbool.h>
7#include <locale.h>
8#include <math.h>
9#include <ctype.h>
10#include <sys/stat.h>
11#include "glibwrapper.h"
12#include "r3types.h"
13#include "inline.h"
14#include "r3util.h"
15
17static bool strtodNew(const char *str, double *v){
18 if (str == NULL || v == NULL || (!isNumber(str))) return false;
19
20 const size_t len = strlen(str);
21 char *mutableStr = (char *)malloc(len + 1);
22 if (!mutableStr) return false;
23
24 // Replace comma with dots
25 for (size_t i = 0; i <= len; ++i) {
26 const char c = str[i];
27 mutableStr[i] = (c == ',') ? '.' : c; // copy also '\0'
28 }
29
30 char *endptr = NULL;
31 *v = strtod(mutableStr, &endptr);
32
33 bool ok = (endptr != mutableStr); // at least one character
34 free(mutableStr);
35 return ok;
36}
37
39static bool polarCheck (PolMat *mat, char *report, size_t maxLen) {
40 double maxInRow, maxInCol;
41 char str [MAX_SIZE_LINE];
42 int cMax, rowMax;
43 report [0] ='\0';
44 for (int c = 1; c < mat->nCol; c += 1) { // check values in line 0 progress
45 if (mat->t [0][c] < mat->t[0][c-1]) {
46 snprintf (str, sizeof str, "Values in row 0 should progress, col: %d; ", c);
47 g_strlcat (report, str, maxLen);
48 }
49 }
50 for (int row = 1; row < mat->nLine; row += 1) {
51 if ((mat->t [row][0] < mat->t[row-1] [0])) {
52 snprintf (str, sizeof str, "Values in col 0 should progress, row: %d; ", row);
53 g_strlcat (report, str, maxLen);
54 }
55 }
56 for (int row = 1; row < mat->nLine; row += 1) {
57 maxInRow = -1.0;
58 cMax = -1;
59 for (int c = 1; c < mat->nCol; c += 1) { // find maxInRow
60 if (mat->t[row][c] > maxInRow) {
61 maxInRow = mat->t[row][c];
62 cMax = c;
63 }
64 }
65 for (int c = 2; c <= cMax; c += 1) {
66 if (mat->t [row][c] < mat->t[row][c-1]) {
67 snprintf (str, sizeof str, "Values in row: %d should progress at col: %d up to maxInRow: %.2lf; ", row, c, maxInRow);
68 g_strlcat (report, str, maxLen);
69 break;
70 }
71 }
72 for (int c = cMax + 1; c < mat->nCol; c += 1) {
73 if ((mat->t [row][c] > mat->t[row][c-1])) {
74 snprintf (str, sizeof str, "Values in row: %d should regress at col: %d after maxInRow: %.2lf; ", row, c, maxInRow);
75 g_strlcat (report, str, maxLen);
76 break;
77 }
78 }
79 }
80
81 for (int c = 1; c < mat->nCol; c += 1) {
82 maxInCol = -1.0;
83 rowMax = -1;
84 for (int row = 1; row < mat->nLine; row += 1) { // find maxInRow
85 if (mat->t[row][c] > maxInCol) {
86 maxInCol = mat->t[row][c];
87 rowMax = row;
88 }
89 }
90 for (int row = 2; row <= rowMax; row += 1) {
91 if (mat->t [row][c] < mat->t[row-1][c]) {
92 snprintf (str, sizeof str, "Values in col: %d should progress at row: %d up to maxInCol: %.2lf; ", c, row, maxInCol);
93 g_strlcat (report, str, maxLen);
94 break;
95 }
96 }
97 for (int row = rowMax + 1; row < mat->nLine; row += 1) {
98 if ((mat->t [row][c] > mat->t[row-1][c])) {
99 snprintf (str, sizeof str, "Values in col: %d should regress at row: %d after maxInCol: %.2lf; ", c, row, maxInCol);
100 g_strlcat (report, str, maxLen);
101 break;
102 }
103 }
104 }
105 return (report [0] == '\0'); // True if no error found
106}
107
110static bool readPolarCsv (const char *fileName, PolMat *mat, char *errMessage, size_t maxLen) {
111 FILE *f = NULL;
112 char buffer [MAX_SIZE_TEXT];
113 char *pLine = &buffer [0];
114 char *strToken;
115 double v = 0.0, max = 0.0;
116 int c;
117
118 errMessage [0] = '\0';
119 strlcpy (mat->jsonHeader, "null", sizeof mat->jsonHeader); // important !
120
121 if ((f = fopen (fileName, "r")) == NULL) {
122 snprintf (errMessage, maxLen, "Error in readPolarCsv: cannot open: %s\n", fileName);
123 return false;
124 }
125 while (fgets (pLine, MAX_SIZE_TEXT, f) != NULL) {
126 c = 0;
127 if (pLine [0] == '#') continue; // ignore if comment
128 if (strpbrk (pLine, CSV_SEP_POLAR) == NULL) continue; // ignore if no separator
129
130 strToken = strtok (pLine, CSV_SEP_POLAR);
131 while ((strToken != NULL) && (c < MAX_N_POL_MAT_COLS)) {
132 if (strtodNew (strToken, &v)) {
133 mat->t [mat->nLine][c] = v;
134 if ((mat->nLine != 0) && (c != 0)) max = fmax (max, v);
135 c += 1;
136 }
137 if ((mat->nLine == 0) && (c == 0)) // whatever accepted including not number at c == l == 0
138 c += 1;
139 strToken = strtok (NULL, CSV_SEP_POLAR);
140 }
141 if (c <= 2) continue; // line is not validated if not at least 2 columns
142 if (c >= MAX_N_POL_MAT_COLS) {
143 snprintf (errMessage, maxLen, "Error in readPolarCsv: max number of colums: %d\n", MAX_N_POL_MAT_COLS);
144 fclose (f);
145 return false;
146 }
147 mat->nLine += 1;
148
149 if (mat->nLine >= MAX_N_POL_MAT_LINES) {
150 snprintf (errMessage, maxLen, "Error in readPolarCsv: max number of line: %d\n", MAX_N_POL_MAT_LINES);
151 fclose (f);
152 return false;
153 }
154 if (mat->nLine == 1) mat->nCol = c; // max
155 }
156 mat->t [0][0] = -1;
157 mat->maxAll = max;
158 fclose (f);
159 return true;
160}
161
163void bestVmg (double tws, PolMat *mat, double *vmgAngle, double *vmgSpeed) {
164 *vmgSpeed = -1;
165 int bidon;
166 double vmg;
167 for (int i = 1; i < mat->nLine; i++) {
168 if (mat->t [i][0] > 90) break; // useless over 90°
169 vmg = findPolar (mat->t [i][0], tws, mat, NULL, &bidon) * cos (DEG_TO_RAD * mat->t [i][0]);
170 if (vmg > *vmgSpeed) {
171 *vmgSpeed = vmg;
172 *vmgAngle = mat->t [i][0];
173 }
174 }
175}
176
178void bestVmgBack (double tws, PolMat *mat, double *vmgAngle, double *vmgSpeed) {
179 *vmgSpeed = -1;
180 int bidon;
181 double vmg;
182 for (int i = 1; i < mat->nLine; i++) {
183 if (mat->t [i][0] < 90) continue; // useless under 90° for Vmg Back
184 vmg = fabs (findPolar (mat->t [i][0], tws, mat, NULL, &bidon) * cos (DEG_TO_RAD * mat->t [i][0]));
185 if (vmg > *vmgSpeed) {
186 *vmgSpeed = vmg;
187 *vmgAngle = mat->t [i][0];
188 }
189 }
190}
191
193char *polToStr (const PolMat *mat, char *str, size_t maxLen) {
194 char line [MAX_SIZE_LINE] = "";
195 str [0] = '\0';
196 for (int i = 0; i < mat->nLine; i++) {
197 for (int j = 0; j < mat->nCol; j++) {
198 snprintf (line, MAX_SIZE_LINE, "%6.2f ", mat->t [i][j]);
199 g_strlcat (str, line, maxLen);
200 }
201 g_strlcat (str, "\n", maxLen);
202 }
203 snprintf (line, MAX_SIZE_LINE, "Number of rows in polar : %d\n", mat->nCol);
204 g_strlcat (str, line, maxLen);
205 snprintf (line, MAX_SIZE_LINE, "Number of lines in polar: %d\n", mat->nLine);
206 g_strlcat (str, line, maxLen);
207 snprintf (line, MAX_SIZE_LINE, "Max : %.2lf\n", mat->maxAll);
208 g_strlcat (str, line, maxLen);
209 snprintf (line, MAX_SIZE_LINE, "nSail : %.zu\n", mat->nSail);
210 g_strlcat (str, line, maxLen);
211 return str;
212}
213
215static bool addSail (PolMat *polMat, int id, char *name, double max) {
216 const int nSail = polMat->nSail;
217 if (nSail >= MAX_N_SAIL - 1) return false;
218 polMat->tSail [nSail].id = id;
219 strlcpy (polMat->tSail [nSail].name, name, MAX_SIZE_NAME);
220 polMat->tSail [nSail].max = max;
221 polMat->nSail += 1;
222 polMat->maxAll = fmax (max, polMat->maxAll);
223 return true;
224}
225
227void wipeSpace(char *str) {
228 char *src = str, *dst = str;
229 while (*src) {
230 if (!isspace((unsigned char)*src)) *dst++ = *src;
231 src++;
232 }
233 *dst = '\0';
234}
235
237static char *findSailPol (char *str, PolMat *polMat, PolMat *sailPolMat, char *message, size_t maxLen) {
238 double sailId, maxVal = 0.0;
239 int nTws = 0, maxNTws= 0, nTwa = 0;
240 char *sailName, *endPtr;
241 char *pt = strstr (str, "\"id\":");
242 if (pt == NULL) return NULL;
243 pt += 5;
244 sailId = strtod (pt, &endPtr);
245 if (endPtr == pt) return NULL;
246 pt = endPtr;
247
248 pt = strstr (str, "\"name\":\"");
249 if (pt == NULL) return NULL;
250 sailName = pt + 8;
251 pt = strchr (sailName, '"');
252 if (pt == NULL) return NULL;
253 *pt = '\0';
254 // printf ("SailName: %s\n", sailName);
255 pt = strstr (pt + 1, "\"speed\":[[");
256 if (pt == NULL) return NULL;
257 pt += 10;
258 // printf ("%s\n", pt-1);
259 while (pt) {
260 nTws = 0;
261 while ((*pt == ',') || (*pt == '[')) pt += 1; // important
262 while (pt) {
263 double val = strtod (pt, &endPtr);
264 if (pt == endPtr) {
265 fprintf (stderr, "In findSailPol, Error: No value at nTwa: %d, nTWs: %d\n", nTwa, nTws);
266 }
267 if ((val >= polMat->t [nTwa + 1][nTws + 1]) && (val > 0.0)) {
268 polMat->t [nTwa + 1][nTws + 1] = val;
269 sailPolMat->t [nTwa + 1][nTws + 1] = sailId;
270 if (fabs (sailId - round (sailId)) > 0.2) {
271 fprintf (stderr, "In findSail, Error: Strange Value for saiId: %.2lf\n", sailId);
272 }
273 maxVal = fmax (val, maxVal);
274 }
275 nTws += 1;
276 if (*endPtr == ']') break;
277 pt = endPtr + 1;
278 }
279 pt = endPtr + 1;
280 maxNTws = fmax (nTws, maxNTws);
281 nTwa += 1;
282 if (*endPtr == ']') { // research of ]]
283 endPtr += 1;
284 if (*endPtr == ']') break;
285 }
286 }
287 if (nTws != polMat->nCol -1) {
288 snprintf (message, maxLen, "nTws = %d and polMat->nCol-1 = %d should be equal\n", nTws, polMat->nCol-1);
289 return NULL;
290 }
291 if (nTwa != polMat->nLine -1) {
292 snprintf (message, maxLen, "nTwa = %d and polMat->nLine-1 = %d should be equal\n", nTwa, polMat->nLine-1);
293 return NULL;
294 }
295
296 if (! addSail (polMat, sailId, sailName, maxVal)) return NULL;
297 return pt;
298}
299
301static char *findListPol (bool isTws, int maxN, char *str, const char *startWith,
302 PolMat *polMat, PolMat *sailPolMat, char *message, size_t maxLen) {
303 char *endPtr;
304 int size = 0;
305 char *pt = strstr (str, startWith);
306 int n;
307 if (pt == NULL) {
308 snprintf (message, maxLen, "In findListPol, Error: %s not found.\n", startWith);
309 return NULL;
310 }
311 pt += strlen (startWith);
312 for (n = 1; pt != NULL && n < maxN; n += 1) {
313 const double val = strtod (pt, &endPtr);
314 if (endPtr == pt) break;
315 if (isTws) polMat->t [0][n] = sailPolMat->t [0][n] = val;
316 else polMat->t [n][0] = sailPolMat->t [n][0] = val;
317 size += 1;
318 if (*endPtr == ']') break;
319 pt = endPtr + 1;
320 }
321 if (n >= maxN) {
322 snprintf (message, maxLen, "In findListPol, Error: maxN reached for %s\n", startWith);
323 return NULL;
324 }
325 if (pt == NULL) {
326 snprintf (message, maxLen, "In findListPol, Error: ] end not found for %s\n", startWith);
327 return NULL;
328 }
329 if (isTws) polMat->nCol = sailPolMat->nCol = size + 1;
330 else polMat->nLine = sailPolMat->nLine = size + 1;
331 return pt;
332}
333
337static bool readPolarJson (const char *fileName, PolMat *polMat, PolMat *sailPolMat, char *errMessage, size_t maxLen) {
338 char start [9000];
339 char *begin, *ptr;
340 errMessage [0] = '\0';
341 char *buffer = readTextFile (fileName, errMessage, maxLen);
342 if (buffer == NULL) return false;
343 wipeSpace (buffer); // buffer contain all JSON specification without spaces
344 if (buffer [0] == '\0') {
345 free (buffer);
346 return false;
347 }
348 char *line = buffer;
349
350 // extract the header
351 begin = strstr (line, "\"_id\"");
352 if (begin == NULL) {
353 snprintf (errMessage, maxLen, "[ _id: not found\n");
354 free (buffer);
355 return false;
356 }
357 ptr = strstr (line, "\"tws\":");
358 if (ptr == NULL) {
359 snprintf (errMessage, maxLen, "\"tws\": not found\n");
360 free (buffer);
361 return false;
362 }
363 strlcpy (start, begin, (ptr-begin));
364 const int len = strlen (start);
365 if (start [len - 1] == ',') start [len - 1 ] = '\0'; // last comma elimination if exist
366 snprintf (polMat->jsonHeader, sizeof polMat->jsonHeader, "{%s\n}", start); // header extracted
367
368 line = findListPol (true, MAX_N_POL_MAT_COLS, line, "\"tws\":[", polMat, sailPolMat, errMessage, maxLen);
369 if (line == NULL) return false;
370 line = findListPol (false, MAX_N_POL_MAT_LINES, line, "\"twa\":[", polMat, sailPolMat, errMessage, maxLen);
371 if (line == NULL) return false;
372 line = strstr (line, "\"sail\":");
373 if (line == NULL) {
374 snprintf (errMessage, maxLen, "\"sail\": not found\n");
375 free (buffer);
376 return false;
377 }
378 line += strlen ("sail") + 2;
379 while (line) {
380 line = findSailPol (line, polMat, sailPolMat, errMessage, maxLen);
381 }
383 free (buffer);
384 return errMessage [0] == '\0';
385}
386
388bool readPolar (const char *fileName, PolMat *mat, PolMat *sailPolMat, char *errMessage, size_t maxLen) {
389 char sailPolFileName [MAX_SIZE_NAME] = "";
390 char bidon [MAX_SIZE_LINE];
391 bool res = false;
392 if (!mat) return false;
393 *mat = (PolMat){0}; // set all to zero
394 if (sailPolMat) *sailPolMat = (PolMat){0}; // set all to zero if not NULL
395
396 if (g_str_has_suffix (fileName, ".json")) {
397 res = readPolarJson (fileName, mat, sailPolMat, errMessage, maxLen);
398 }
399 else {
400 res = readPolarCsv (fileName, mat, errMessage, maxLen);
401 if (res && sailPolMat != NULL) { // read additional polar for sail numbers
402 newFileNameSuffix (fileName, "sailpol", sailPolFileName, sizeof (sailPolFileName));
403 if (readPolarCsv (sailPolFileName, sailPolMat, bidon, sizeof bidon)) { // sailPolFile not mandatory
404 mat->nSail = sailPolMat->maxAll; // Number of sail max is the number of sails
405 for (size_t i = 0; i < mat->nSail && i < sailNameSize; i += 1)
406 strlcpy (mat->tSail [i].name, sailName [i], MAX_SIZE_NAME);
407
408 if (sailNameSize < mat->nSail) {
409 fprintf (stderr, "in readPolar, Error: size of sailName: %zu not enough for nSail: %zu\n", sailNameSize, mat->nSail);
410 }
411 }
412 else mat->nSail = 1;
413 }
414 }
415 return res;
416}
417
419char *polToStrJson (bool report, const char *fileName, const char *objName, char *out, size_t maxLen) {
420 char polarName [MAX_SIZE_FILE_NAME];
421 char errMessage [MAX_SIZE_LINE];
422 char str [MAX_SIZE_TEXT] = "";;
423 PolMat mat, sailMat;
424 buildRootName (fileName, polarName, sizeof (polarName));
425 out [0] = '\0';
426
427 if (!readPolar (polarName, &mat, &sailMat, errMessage, sizeof (errMessage))) {
428 fprintf (stderr, "%s", errMessage);
429 snprintf (out, maxLen, "{}\n");
430 return out;
431 }
432 if ((mat.nLine < 2) || (mat.nCol < 2)) {
433 fprintf (stderr, "In polToStrJson Error: no value in: %s\n", polarName);
434 snprintf (out, maxLen, "{}\n");
435 return out;
436 }
437
438 snprintf (out, maxLen,
439 "{\"header\": %s,\n\"%s\": \"%s\", \"nLine\": %d, \"nCol\": %d, \"nSail\": %zu, \"max\": %.2lf, \"fromJson\": %s, \n\"array\":\n[\n",
440 mat.jsonHeader, objName, polarName, mat.nLine, mat.nCol, mat.nSail, mat.maxAll, mat.fromJson ? "true" : "false");
441
442 // generate two dimensions array with the values
443 for (int i = 0; i < mat.nLine ; i++) {
444 g_strlcat (out, " [", maxLen);
445 for (int j = 0; j < mat.nCol - 1; j++) {
446 snprintf (str, sizeof str, "%.4f, ", mat.t [i][j]);
447 g_strlcat (out, str, maxLen);
448 }
449 snprintf (str, sizeof (str), "%.4f]%s\n", mat.t [i][mat.nCol -1], (i < mat.nLine - 1) ? "," : "");
450 g_strlcat (out, str, maxLen);
451 }
452 g_strlcat (out, "]", maxLen);
453
454 // if several sails, generate two dimensions array with sail number
455 if (mat.nSail > 1) {
456 g_strlcat (out, ",\n\"arraySail\":\n[\n", maxLen);
457
458 for (int i = 0; i < mat.nLine ; i++) {
459 g_strlcat (out, " [", maxLen);
460 for (int j = 0; j < mat.nCol - 1; j++) {
461 snprintf (str, sizeof str, "%.0f, ", sailMat.t [i][j]);
462 g_strlcat (out, str, maxLen);
463 }
464 snprintf (str, sizeof (str), "%.0f]%s\n", sailMat.t [i][mat.nCol -1], (i < mat.nLine - 1) ? "," : "");
465 g_strlcat (out, str, maxLen);
466 }
467 g_strlcat (out, "],\n", maxLen);
468
469 // generate one dimension array that list the name of sails, ordered NA = 0, Sail1, sail2 etc
470 g_strlcat (out, "\"legend\": [", maxLen);
471 g_strlcat (out, "\"NA\",", maxLen); // first is NA (id 0)
472 for (size_t i = 0; i < mat.nSail; i += 1) {
473 snprintf (str, sizeof str, "\"%s\"%s", mat.tSail [i].name, (i < mat.nSail -1) ? ", " : "");
474 g_strlcat (out, str, maxLen);
475 }
476 g_strlcat (out, "]", maxLen);
477 } // end if mat.nSail > 1
478
479 // generate report
480 if (report) {
481 g_strlcat (out, ",\n\"report\": \"", maxLen);
482 polarCheck (&mat, str, sizeof str);
483 g_strlcat (out, str, maxLen);
484 g_strlcat (out, "\"", maxLen);
485 }
486 g_strlcat (out, "\n}\n", maxLen);
487 return out;
488}
#define g_strlcat(dest, src, size)
Definition glibwrapper.h:10
static bool g_str_has_suffix(const char *s, const char *suffix)
Equivalent to Glib g_str_has_suffix.
static double findPolar(double twa, double w, const PolMat *mat, const PolMat *sailMat, int *sail)
find in polar boat speed or wave coeff
Definition inline.h:174
char * polToStrJson(bool report, const char *fileName, const char *objName, char *out, size_t maxLen)
write polar information in string Json format
Definition polar.c:419
void bestVmgBack(double tws, PolMat *mat, double *vmgAngle, double *vmgSpeed)
return VMG back: angle and speed at TWS: vent arriere
Definition polar.c:178
void bestVmg(double tws, PolMat *mat, double *vmgAngle, double *vmgSpeed)
return VMG: angle and speed at TWS: pres
Definition polar.c:163
static bool addSail(PolMat *polMat, int id, char *name, double max)
add a new sail in PoMat object
Definition polar.c:215
void wipeSpace(char *str)
wipe all spaces within str
Definition polar.c:227
static bool readPolarCsv(const char *fileName, PolMat *mat, char *errMessage, size_t maxLen)
read polar file and fill poLMat matrix if check then polarCheck
Definition polar.c:110
bool readPolar(const char *fileName, PolMat *mat, PolMat *sailPolMat, char *errMessage, size_t maxLen)
Launch readPolarCsv or readPolarJson according to type.
Definition polar.c:388
static char * findSailPol(char *str, PolMat *polMat, PolMat *sailPolMat, char *message, size_t maxLen)
update polMat and sailPolMat with new sail found in Json str
Definition polar.c:237
static bool readPolarJson(const char *fileName, PolMat *polMat, PolMat *sailPolMat, char *errMessage, size_t maxLen)
read polar in json format (eg.
Definition polar.c:337
static bool polarCheck(PolMat *mat, char *report, size_t maxLen)
Check polar and return false and a report if something to say.
Definition polar.c:39
char * polToStr(const PolMat *mat, char *str, size_t maxLen)
write polar information in string
Definition polar.c:193
static char * findListPol(bool isTws, int maxN, char *str, const char *startWith, PolMat *polMat, PolMat *sailPolMat, char *message, size_t maxLen)
update polMat and sailPolMat this tws ans twa lists found in Json str
Definition polar.c:301
static bool strtodNew(const char *str, double *v)
compilation: gcc -c polar.c
Definition polar.c:17
#define DEG_TO_RAD
Definition r3types.h:28
#define MAX_N_SAIL
Definition r3types.h:72
#define MAX_N_POL_MAT_COLS
Definition r3types.h:41
#define MAX_SIZE_NAME
Definition r3types.h:61
#define MAX_N_POL_MAT_LINES
Definition r3types.h:42
#define MAX_SIZE_FILE_NAME
Definition r3types.h:63
#define MAX_SIZE_LINE
Definition r3types.h:45
#define CSV_SEP_POLAR
Definition r3types.h:11
#define MAX_SIZE_TEXT
Definition r3types.h:48
bool isNumber(const char *name)
true if name contains a number
Definition r3util.c:174
const size_t sailNameSize
sail attributes
Definition r3util.c:38
char * buildRootName(const char *fileName, char *rootName, size_t maxLen)
Build root name if not already a root name.
Definition r3util.c:230
PolMat polMat
polar matrix description
Definition r3util.c:49
PolMat sailPolMat
polar matrix for sails
Definition r3util.c:52
char * readTextFile(const char *fileName, char *errMessage, size_t maxLen)
read all text file in buffer.
Definition r3util.c:1106
const char * sailName[]
Definition r3util.c:39
char * newFileNameSuffix(const char *fileName, const char *suffix, char *newFileName, size_t maxLen)
replace former suffix (after last dot) by suffix example : "pol/bibi.toto.csv" with suffix "sailpol" ...
Definition r3util.c:78
char name[MAX_SIZE_NAME]
Definition r3util.c:22
polar Matrix description
Definition r3types.h:201
bool fromJson
Definition r3types.h:207
char name[MAX_SIZE_NAME]
Definition r3types.h:211
double maxAll
Definition r3types.h:204
char jsonHeader[MAX_SIZE_JSON_HEADER]
Definition r3types.h:202
double max
Definition r3types.h:212
struct PolMat::@9 tSail[MAX_N_SAIL]
double t[MAX_N_POL_MAT_LINES][MAX_N_POL_MAT_COLS]
Definition r3types.h:203
int nLine
Definition r3types.h:205
size_t nSail
Definition r3types.h:208
int id
Definition r3types.h:210
int nCol
Definition r3types.h:206