Frankiezafe (Talk | contribs) (→remap method()) |
Frankiezafe (Talk | contribs) (→functions (js)) |
||
Line 33: | Line 33: | ||
} | } | ||
− | + | ''cyclic_bound'' is applied on all entries of the mapping function. | |
+ | |||
+ | Mapping the value, steps: | ||
+ | |||
+ | * calculation of the middle of the world range (''from_in'',''from_out''), divided by 2, ''half'' | ||
+ | * bounding of value to map in the world range | ||
+ | * bounding of lower limit of the new range (''to_in'' > ''bin'') in the world range | ||
+ | * bounding of lower limit of the new range (''to_out'' > ''bout'') in the world range | ||
+ | * calculation and bounding of middle of the new range (''bmid'') in the world range | ||
+ | |||
+ | Once done, we have everything we need to render the value '''mapped''' form the world range to the new range. Note that the returned value will also be '''bounded''' to world range. | ||
+ | |||
+ | The process to do so: | ||
+ | |||
+ | * Calculation of the distance between the bounded value and the middle of the new range. This returns a value between -''half'' and ''half''. Because we will have to map this distance to the new range, we have to divide it by ''half''. This returns a percentage. Its value is in the range [-2, 2]. Indeed, the value to map might be at the opposite of the the middle of the new range. Because world space is cyclic, if the absolute value of the percentage is greater than 1, 1.5 for instance, the value can be bounded in the range [-1, 1]. The 1.5 becomes -0.5, and it's still the same value. | ||
+ | * Calculation of the new range. The distance between one of the limits ( ''to_in'' or ''to_out'' ) and their center (''bmid') has to be removed form the half of the world range. Once done, the new range might exceed the half of the world range, when ''to_in'' was smaller than the lower limit of the world, for instance. Therefore, we have to bound the new range between -''half'' and ''half''. From now on, the percentage and the new range can be multiply by one another . | ||
+ | * Last step is to check the sign of the percentage. If it is positive, the limit to use is the highest one, '''bout'''. We add the percentage of the half world range and returns the value. If it is negative, the process is similar but uses the lower limit '''bin'''. | ||
function cyclic_map( value, from_in, from_out, to_in, to_out ) { | function cyclic_map( value, from_in, from_out, to_in, to_out ) { | ||
Line 52: | Line 68: | ||
} | } | ||
+ | |||
+ | === identification of the nearest limit === | ||
+ | |||
+ | // code to indentify closest limit | ||
+ | |||
+ | // possible configurations of the In, Mid and Out: | ||
+ | // I M O > "normal" | ||
+ | // M O I > "rejected in" | ||
+ | // O I M > "rejected out" | ||
+ | |||
+ | // booleans normal therm speciaL term restriction | ||
+ | boolean cnormal = (bin <= bmid) && (bmid < bout); | ||
+ | boolean crejected_in = (bmid <= bout) && (bin > bmid); | ||
+ | boolean crejected_out = (bin <= bmid) && (bout < bmid) && !cnormal; | ||
+ | |||
+ | if ( | ||
+ | cnormal && | ||
+ | ( | ||
+ | ( bvalue <= bmid && bvalue >= bmid - half ) || | ||
+ | bvalue >= bmid + half | ||
+ | ) | ||
+ | ) { | ||
+ | return bin; | ||
+ | } else if ( | ||
+ | crejected_in && | ||
+ | ( | ||
+ | bvalue <= bmid || | ||
+ | bvalue > bmid + half | ||
+ | ) | ||
+ | ) { | ||
+ | return bin; | ||
+ | } else if ( | ||
+ | crejected_out && | ||
+ | ( | ||
+ | bvalue < bmid && | ||
+ | bvalue >= bmid - half | ||
+ | ) | ||
+ | ) { | ||
+ | return bin; | ||
+ | } | ||
+ | return bout; | ||
== research == | == research == |
La question traitée ici concerne le mapping de données dans un espace cyclique. Le traitement d'angle est le premier qui me vient en tête.
manipulation:
code:
First important method is cyclic_bound. Its role is to remap any value in the given range [from_in,from_out]. It's a modulo in both directions.
function cyclic_bound( value, from_in, from_out ) { if ( value >= from_in && value <= from_out ) { return value; } var d = from_out - from_in; while( value < from_in ) { value += d; } while( value > from_out ) { value -= d; } return value; }
cyclic_bound is applied on all entries of the mapping function.
Mapping the value, steps:
Once done, we have everything we need to render the value mapped form the world range to the new range. Note that the returned value will also be bounded to world range.
The process to do so:
function cyclic_map( value, from_in, from_out, to_in, to_out ) { var half = ( from_out - from_in ) * 0.5; var bvalue = cyclic_bound( value, from_in, from_out ); var bin = cyclic_bound( to_in, from_in, from_out ); var bout = cyclic_bound( to_out, from_in, from_out ); var bmid = cyclic_bound( to_in + ( to_out - to_in ) * 0.5, from_in, from_out ); var pc = cyclic_bound( ( bvalue - bmid ) / half, -1, 1 ); var brange = cyclic_bound( half - ( bmid - bin ), -half, half ); if ( pc >= 0 ) { return cyclic_bound( bout + (brange * pc), from_in, from_out ); } return cyclic_bound( bin + (brange * pc), from_in, from_out ); }
// code to indentify closest limit // possible configurations of the In, Mid and Out: // I M O > "normal" // M O I > "rejected in" // O I M > "rejected out" // booleans normal therm speciaL term restriction boolean cnormal = (bin <= bmid) && (bmid < bout); boolean crejected_in = (bmid <= bout) && (bin > bmid); boolean crejected_out = (bin <= bmid) && (bout < bmid) && !cnormal; if ( cnormal && ( ( bvalue <= bmid && bvalue >= bmid - half ) || bvalue >= bmid + half ) ) { return bin; } else if ( crejected_in && ( bvalue <= bmid || bvalue > bmid + half ) ) { return bin; } else if ( crejected_out && ( bvalue < bmid && bvalue >= bmid - half ) ) { return bin; } return bout;
|--------*-----------------*-----------*--------------*--------| 0 a b c d 2PI
l´idée est d´écarter 2 valeurs consécutives, b et c par ex, et de rediffuser les 2 autres, a et d, de manière proportionnelle
pour ce faire > calcul du point médian x
|--------*-----------------*-----!-----*--------------*--------| 0 a b x c d 2PI
distance bx = (c-b) x = b + bx/2
le remap spécifie les nouvelles valeurs de b et de c
|--------*--------<--------*-----!-----*-------->------*--------| 0 a b´ b x c c´ d 2PI
distance b´x = (c´-b´) x = b + bx/2
on a donc perdu (b´x - bx) radians
|----*---------|----*---------|----*---------| -2PI a´ 0 a 2PI a´´ 4PI
ce qu´il ne faut pas oublier: l´espace est cyclique > a´ ~ a ~ a´´
on peut descendre en négatif et passer 2PI sans que ça pose de réel problème
|---!--------*-----------*-----*----------*-----|---!--------* 0 x´ a b c d 2PI x a´ 3 11 22 27 37 42 45 53
l´angle entre d et a est à plusieurs positions simultanément pour son calcul: ( d + a ) / 2 - ( 37 + 11 ) -> 48!!!!, divisé par 2, on arrive à 24, donc pas du tout où il faut! il faut ajouter 42 à a => 53, et là: (37+57)/2, 90/2 => 45 paf! si a < d,
a += 2PI
center = (d+a)/2
dans le remap, je demande un recalcul de b dans les bornes d > a vers d-5, a + 5
a, in, out, in_to, out_to b, 11, 37, 16, 32
|-----------*--->--*---*---*----------*---<--*-----| 0 | | | | | | 2PI a | c b | d 11 | 19 22 | 37 0 |´ | | | | \ | | a´ c´ b´ d´ 16 20.9 22.8 32
? b´
distance_b distance_init distance_new percent_b out_b si b < d:
distance_b = b - a => 11 distance_init = d - a => 26 distance_new = d´ - a´ => 16 percent_b = distance_b / distance_init = > 0.423076923 out_b = a´ + percent_b * distance_new (6.769230769) => 22.769230769
return out_b
pour c´ si c < d:
distance_c = b - a => 8 distance_init = d - a => 26 distance_new = d´ - a´ => 16 percent_b = distance_c / distance_init = > 0.307692308 out_b = a´ + percent_b * distance_new (4.923076923) => 20.923076923
return out_b
le process semble ok pour les angles compris entre a et d
online identity ∋ [ social ∋ [mastodon♥, twitter®, facebook®, diaspora, linkedin®]
∥ repos ∋ [github®, gitlab♥, bitbucket®, sourceforge] ∥ media ∋ [itch.io®, vimeo®, peertube♥, twitch.tv®, tumblr®] ∥ communities ∋ [godotengine♥, openprocessing, stackoverflow, threejs]]