1 /**
2     Utility functions.
3 
4     Copyright: 
5         Copyright © 2020-2026, Inochi2D Project
6     
7     License:
8         $(LINK2 https://github.com/Inochi2D/inochi2d/blob/main/LICENSE, BSD 2-clause License)
9 
10     Authors:
11         Luna Nielsen
12 */
13 module inochi2d.param.utils;
14 import inochi2d.core.vector2d;
15 import inochi2d.core.serde;
16 import inochi2d.common;
17 import inochi2d.param;
18 import numath;
19 import nulib;
20 import numem;
21 
22 /**
23     Deserializes a legacy 0.8 style nested array to the new flat format.
24 
25     Params:
26         object =    The DataNode to extract the data from.
27         target =    The target to store the data within.
28         state =     The state of the deserializer.
29         dims =      The dimensionality expected.
30 */
31 void deserialize08NestedArrays(T)(ref DataNode object, ref T target, ref ModelState state, vec2u dims) @nogc
32 if (is(T == vector2d!U, U)) {
33     import inochi2d.core.math.deform : Deformation;
34 
35     // Invalid array.
36     if (!object.isArray) {
37         state.error(nstring("expected array, got ", object.type.toTypeName, "!"));
38         return;
39     }
40 
41     target.resize(dims.x, dims.y);
42 
43     // The Y axis is shorter than expected.
44     if (object.length < dims.y) {
45         state.error("fewer elements were found in the y axis than were expected!");
46         return;
47     }
48 
49     // Iterate through all elements, adding them to the given index in the
50     // target.
51     size_t px = 0;
52     size_t py = 0;
53     foreach (ref DataNode elem; object.array) {
54 
55         // Not nested??
56         if (!elem.isArray) {
57             state.error(nstring("expected nested array, got ", elem.type.toTypeName, "!"));
58             return;
59         }
60 
61         // Too short?
62         if (elem.length < dims.x) {
63             state.error("fewer elements were found in the x axis than were expected!");
64             return;
65         }
66 
67         foreach (ref value; elem.array) {
68             target[px, py] = value.deserialize!(T.DT)(state);
69             px++;
70         }
71         py++;
72         px = 0;
73     }
74 }
75 
76 /**
77     Resizes the given vector2d to fit the element counts
78     of the given parameter.
79 
80     Params:
81         vec2d = The target vector2d.
82         param = The parameter. 
83 */
84 void resizeToParam(T)(ref T vec2d, Parameter param) {
85     if (param.dimensions == 1) {
86         vec2d.resize(1, param.elementCounts[0]);
87     } else if (param.dimensions == 2) {
88         vec2d.resize(param.elementCounts[0], param.elementCounts[1]);
89     }
90 }
91 
92 /**
93     Interpolates between keypoints.
94 */
95 T interpolateKeypoint(T)(ref vector2d!T values, vec2u index, vec2 norm) @nogc {
96     return T.init;
97 }