Perspective transformation with GD - php

How can I apply a perspective transformation on an image
using only the PHP GD library?
I don't want to use a function someone else made I want to UNDERSTAND what's going on

I honestly don't know how to describe mathematically a perspective distortion. You could try searching the literature for that (e.g. Google Scholar). See also in the OpenGL documentation, glFrustum.
EDIT: Interestingly, starting with version 8, Mathematica has a ImagePerspectiveTransformation. In the relevant part, it says:
For a 3*3 matrix m, ImagePerspectiveTransformation[image,m] applies LinearFractionalTransform[m] to image.
This is a transformation that, for some a (matrix), b (vector), c (vector) and d (scalar), transforms the vector r to (a.r+b)/(c.r+d). In a 2D situation, this gives the homogeneous matrix:
a_11 a_12 b_1
a_21 a_22 b_2
c_1 c_2 d
To apply the transformation, you multiply this matrix by the column vector extended with z=1 and then take the first two elements of the result and divide them by the third:
{{a11, a12, b1}, {a21, a22, b2}, {c1, c2, d}}.{{x}, {y}, {1}} // #[[
1 ;; 2, All]]/#[[3, 1]] & // First /# # &
which gives:
{(b1 + a11 x + a12 y)/(d + c1 x + c2 y),
(b2 + a21 x + a22 y)/(d + c1 x + c2 y)}
With the example:
a = {{0.9, 0.1}, {0.3, 0.9}}
b = {0, -0.1}
c = {0, 0.1}
d = 1
You get this transformation:
im = Import["/home/cataphract/Downloads/so_q.png"];
orfun = BSplineFunction[ImageData[im], SplineDegree -> 1];
(*transf=TransformationFunction[{{0.9, 0.1, 0.}, {0.3,
0.9, -0.1}, {0., 0.1, 1.}}] -- let's expand this:*)
transf = {(0.9 x + 0.1 y)/(1.+ 0.1 y), (-0.1 + 0.3 x + 0.9 y)/(
1. + 0.1 y)} /. {x -> #[[1]], y -> #[[2]]} &;
ParametricPlot[transf[{x, y}], {x, 0, 1}, {y, 0, 1},
ColorFunction -> (orfun[1 - #4, #3] &),
Mesh -> None,
FrameTicks -> None,
Axes -> False,
ImageSize -> 200,
PlotRange -> All,
Frame -> False
]
Once you have a map that describes the position of a point of the final image in terms of a point in the original image, it's just a matter of finding its value for each of the points in the new image.
There's one additional difficulty. Since an image is discrete, i.e., has pixels instead of continuous values, you have to make it continuous.
Say you have a transformation that doubles the size of an image. The function to calculate a point {x,y} in the final image will look for point {x/2, y/2} in the original. This point doesn't exist, because images are discrete. So you have to interpolate this point. There are several possible strategies for this.
In this Mathematica example, I do a simple 2D rotation and use a degree-1 spline function to interpolate:
im = Import["d:\\users\\cataphract\\desktop\\img.png"]
orfun = BSplineFunction[ImageData[im], SplineDegree -> 1];
transf = Function[{coord}, RotationMatrix[20. Degree].coord];
ParametricPlot[transf[{x, y}], {x, 0, 1}, {y, 0, 1},
ColorFunction -> (orfun[1 - #4, #3] &), Mesh -> None,
FrameTicks -> None, Axes -> None, ImageSize -> 200,
PlotRange -> {{-0.5, 1}, {0, 1.5}}]
This gives:
PHP:
For the interpolation, google for "B-spline". The rest is as follows.
First choose a referential for the original image, say if the image is 200x200, pixel (1,1) maps (0,0) and pixel (200,200) maps to (1,1).
Then you have to guess where your final image will land when the transformation is applied. This depends on the transformation, you can e.g. apply it to the corners of the image or just guess.
Say you consider the mapped between (-.5,0) and (1, 1.5) like I did and that your final image should be 200x200 also. Then:
$sizex = 200;
$sizey = 200;
$x = array("min"=>-.5, "max" => 1);
$y = array("min"=>0, "max" => 1.5);
// keep $sizex/$sizey == $rangex/$rangey
$rangex = $x["max"] - $x["min"];
$rangey = $y["max"] - $y["min"];
for ($xp = 1; $xp <= $sizex; $xp++) {
for ($yp = 1; $yp <= $sizey; $yp++) {
$value = transf(
(($xp-1)/($sizex-1)) * $rangex + $x["min"],
(($yp-1)/($sizey-1)) * $rangey + $y["min"]);
/* $value should be in the form array(r, g, b), for instance */
}
}

Related

Rotate K coplanar points to a plane parallel to x,y plane

I'm working in php with 3D geometries(not the best choice,I know...).
I have K coplanar 3D points, also with x,y,z value. Together they form a polygon. I need to triangulate this polygon. I have already a working delaunay traingulation function which works for 2D Polygons.
So I want to rotate the given points, so that they lay on a plane parallel to the x,y plane. After that I can triangulated it using the x,y values. The following pseudocode shall describe how I want to get to this goal.
I build up the following code with reference on this (I'm usign the answer accepted from the OP): https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d, but it doesn't work as I expected. In order to know if it worked, every mapped point shall then have the same 'z' value.
Here is the question, how do I get the correct rotation matrix? Or did I made a conceptual mistake?
function matrixRotationMapping(Point $p, Point $q, Point $r)
{
$normalPolygon =calculatePlaneNormal($p, $q, $r);
$v = crossProduct($normalPolygon, new Point(0, 0, 1));
$c = dotProduct($normalPolygon, new Point(0, 0, 1));
$matrix = buildRotationMatrix($v, $c);
return $matrix;
}
function buildRotationMatrix($v, $c)
{
$R2 = new Matrix(array(array(1, -$v->z, $v->y), array($v->z, 1, -$v->x), array(-$v->y, $v->x, 1)));
$costant = 1/(1+$c);
$R3 = multiplyMatrices($R2, $R2);
$R3 = multiplyMatricesWithFactor($R3, $costant);
$finalMatrix = sumMatrices($R2, $R3);
return $finalMatrix;
}
function calc2DMapping($points)
{
$rotationMatrix = matrixRotationMapping($points[0], $points[1], $points[2]);
foreach($points as $point)
{
$mappedPoint = $rotationMatrix->multiplyWithPoint($point);
$mappedPoints[] = new MappedPoint($mappedPoint);
}
}
I found another helpful description of the problem, but I wasn't able to implement it: Mapping coordinates from plane given by normal vector to XY plane
Thanks in advance for your attention.
You need basis vectors X,Y,Z first. So let take the mid point A and two distant points to it B,C (not on single line) from your data set first. The X,Y should lie in the plane and Z should be normal to it so:
X = B-A // any non zero vector inside plane
X = X / |X| // unit in size
Y = C-A // any non zero vector inside plane
(X.Y) != 0 // but not parallel to X !!!
Y = Y / |Y| // unit in size
Compute normal to the plane your points lie in and correct Y axis.
Z = X x Y // cross product gives you perpendicular vector
Y = Z x X // now all vectors are perpendicular and unit
So feed these 3 vectors to rotation part of your transform matrix and set origin to A. But as you need to go from your data set to the plane local coordinate you need inverse matrix (or use pseudo inverse based on transposing)
Anyway now with the basis vectors you can map your plane parametrically like this:
P(u,v) = A + u*X + v*Y
Where u,v = <-inf,+inf> are surface distances form A in X,Y directions. That can get handy sometimes. If you need to compute u,v from P then exploit dot product:
u = ((P-A).X) = dot(P-A,X)
v = ((P-A).Y) = dot(P-A,Y)
Which can be also used to transform to 2D instead of using matrix ...

Calculate the closest colourblind-friendly colour?

How can I calculate the closest colourblind-friendly colour from a HEX colour code like #0a87af or from the three RGB values (0-255).
I'm searching for an efficient way to calculate or do this so I can implement it in PHP or Python and the algorithm can be used for better website accessibility for colourblind people.
As the others mentionned in their comments/answer, the contrast between two colours will be of importance.
The W3 already created a method defining a minimum contrast between colours in order to pass dfferent levels of accessibility.
They provide the description here and the formula to calculate it is on the same page, at the bottom, here :
contrast ratio = (L1 + 0.05) / (L2 + 0.05)
For this apparently simple formula, you will need to calculate the relative luminance noted L1 and L2 of both colours using an other formula that you find here :
L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:
if RsRGB <= 0.03928 then R = RsRGB/12.92 else R = ((RsRGB+0.055)/1.055) ^ 2.4
if GsRGB <= 0.03928 then G = GsRGB/12.92 else G = ((GsRGB+0.055)/1.055) ^ 2.4
if BsRGB <= 0.03928 then B = BsRGB/12.92 else B = ((BsRGB+0.055)/1.055) ^ 2.4
and RsRGB, GsRGB, and BsRGB are defined as:
RsRGB = R8bit/255
GsRGB = G8bit/255
BsRGB = B8bit/255
The minimum contrast ratio between text and background should be of 4.5:1 for level AA and 7:1 for level AAA. This still leaves room for creation of nice designs.
There is an example of implementation in JS by Lea Verou.
This won't give you the closest color as you asked, because on a unique background there will more than one front colour giving the same contrast result, but it's a standard way of calculating contrasts.
A single color is not a problem for color-blind users (unless you want to transport a very specific meaning of that color tone); the difference between colors is.
Given two or more colors, you can convert them to HLS using colorsys and check whether the difference in Lightness is sufficient. If the difference is too small, increase it, like this:
import colorsys
import re
def rgb2hex(r, g, b):
return '#%02x%02x%02x' % (r, g, b)
def hex2rgb(hex_str):
m = re.match(
r'^\#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$', hex_str)
assert m
return (int(m.group(1), 16), int(m.group(2), 16), int(m.group(3), 16))
def distinguish_hex(hex1, hex2, mindiff=50):
"""
Make sure two colors (specified as hex codes) are sufficiently different.
Returns the two colors (possibly changed). mindiff is the minimal
difference in lightness.
"""
rgb1 = hex2rgb(hex1)
rgb2 = hex2rgb(hex2)
hls1 = colorsys.rgb_to_hls(*rgb1)
hls2 = colorsys.rgb_to_hls(*rgb2)
l1 = hls1[1]
l2 = hls2[1]
if abs(l1 - l2) >= mindiff: # ok already
return (hex1, hex2)
restdiff = abs(l1 - l2) - mindiff
if l1 >= l2:
l1 = min(255, l1 + restdiff / 2)
l2 = max(0, l1 - mindiff)
l1 = min(255, l2 + mindiff)
else:
l2 = min(255, l2 + restdiff / 2)
l1 = max(0, l2 - mindiff)
l2 = min(255, l1 + mindiff)
hsl1 = (hls1[0], l1, hls1[2])
hsl2 = (hls2[0], l2, hls2[2])
rgb1 = colorsys.hls_to_rgb(*hsl1)
rgb2 = colorsys.hls_to_rgb(*hsl2)
return (rgb2hex(*rgb1), rgb2hex(*rgb2))
print(distinguish_hex('#ff0000', '#0000ff'))
Contrast-Finder is an open source online tool (written by Open-S and M. Faure) that, given foreground and background colors, will calculate the contrast ratio and if it's insufficient according to WCAG formula, will give you a bunch of background OR foreground colors with sufficient contrast ratio and thus options, using different algorithms (you must tell it if you want to keep the foreground color or the background color and if you want contrast ratio higher than 4.5:1 or 3:1 - level AA - or 7:1 / 4.5:1 - level AAA).
It's pretty spot on for many couples of colors.
Sources - in Java - are on GitHub.
Note: as already written in other answers, colourblind people ("people with colour deficiencies") are only a part of people concerned by the choice of colors: partially sighted people also are. And when a webdesigner chooses #AAA on #FFF, it's a problem for many people without any loss of sight or colour perception; they just've a shiny Retina® screen in non-optimal light conditions... :p

Finding n-th permutation without computing others

Given an array of N elements representing the permutation atoms, is there an algorithm like that:
function getNthPermutation( $atoms, $permutation_index, $size )
where $atoms is the array of elements, $permutation_index is the index of the permutation and $size is the size of the permutation.
For instance:
$atoms = array( 'A', 'B', 'C' );
// getting third permutation of 2 elements
$perm = getNthPermutation( $atoms, 3, 2 );
echo implode( ', ', $perm )."\n";
Would print:
B, A
Without computing every permutation until $permutation_index ?
I heard something about factoradic permutations, but every implementation i've found gives as result a permutation with the same size of V, which is not my case.
Thanks.
As stated by RickyBobby, when considering the lexicographical order of permutations, you should use the factorial decomposition at your advantage.
From a practical point of view, this is how I see it:
Perform a sort of Euclidian division, except you do it with factorial numbers, starting with (n-1)!, (n-2)!, and so on.
Keep the quotients in an array. The i-th quotient should be a number between 0 and n-i-1 inclusive, where i goes from 0 to n-1.
This array is your permutation. The problem is that each quotient does not care for previous values, so you need to adjust them. More explicitly, you need to increment every value as many times as there are previous values that are lower or equal.
The following C code should give you an idea of how this works (n is the number of entries, and i is the index of the permutation):
/**
* #param n The number of entries
* #param i The index of the permutation
*/
void ithPermutation(const int n, int i)
{
int j, k = 0;
int *fact = (int *)calloc(n, sizeof(int));
int *perm = (int *)calloc(n, sizeof(int));
// compute factorial numbers
fact[k] = 1;
while (++k < n)
fact[k] = fact[k - 1] * k;
// compute factorial code
for (k = 0; k < n; ++k)
{
perm[k] = i / fact[n - 1 - k];
i = i % fact[n - 1 - k];
}
// readjust values to obtain the permutation
// start from the end and check if preceding values are lower
for (k = n - 1; k > 0; --k)
for (j = k - 1; j >= 0; --j)
if (perm[j] <= perm[k])
perm[k]++;
// print permutation
for (k = 0; k < n; ++k)
printf("%d ", perm[k]);
printf("\n");
free(fact);
free(perm);
}
For example, ithPermutation(10, 3628799) prints, as expected, the last permutation of ten elements:
9 8 7 6 5 4 3 2 1 0
Here's a solution that allows to select the size of the permutation. For example, apart from being able to generate all permutations of 10 elements, it can generate permutations of pairs among 10 elements. Also it permutes lists of arbitrary objects, not just integers.
function nth_permutation($atoms, $index, $size) {
for ($i = 0; $i < $size; $i++) {
$item = $index % count($atoms);
$index = floor($index / count($atoms));
$result[] = $atoms[$item];
array_splice($atoms, $item, 1);
}
return $result;
}
Usage example:
for ($i = 0; $i < 6; $i++) {
print_r(nth_permutation(['A', 'B', 'C'], $i, 2));
}
// => AB, BA, CA, AC, BC, CB
How does it work?
There's a very interesting idea behind it. Let's take the list A, B, C, D. We can construct a permutation by drawing elements from it like from a deck of cards. Initially we can draw one of the four elements. Then one of the three remaining elements, and so on, until finally we have nothing left.
Here is one possible sequence of choices. Starting from the top we're taking the third path, then the first, the the second, and finally the first. And that's our permutation #13.
Think about how, given this sequence of choices, you would get to the number thirteen algorithmically. Then reverse your algorithm, and that's how you can reconstruct the sequence from an integer.
Let's try to find a general scheme for packing a sequence of choices into an integer without redundancy, and unpacking it back.
One interesting scheme is called decimal number system. "27" can be thought of as choosing path #2 out of 10, and then choosing path #7 out of 10.
But each digit can only encode choices from 10 alternatives. Other systems that have a fixed radix, like binary and hexadecimal, also can only encode sequences of choices from a fixed number of alternatives. We want a system with a variable radix, kind of like time units, "14:05:29" is hour 14 from 24, minute 5 from 60, second 29 from 60.
What if we take generic number-to-string and string-to-number functions, and fool them into using mixed radixes? Instead of taking a single radix, like parseInt('beef', 16) and (48879).toString(16), they will take one radix per each digit.
function pack(digits, radixes) {
var n = 0;
for (var i = 0; i < digits.length; i++) {
n = n * radixes[i] + digits[i];
}
return n;
}
function unpack(n, radixes) {
var digits = [];
for (var i = radixes.length - 1; i >= 0; i--) {
digits.unshift(n % radixes[i]);
n = Math.floor(n / radixes[i]);
}
return digits;
}
Does that even work?
// Decimal system
pack([4, 2], [10, 10]); // => 42
// Binary system
pack([1, 0, 1, 0, 1, 0], [2, 2, 2, 2, 2, 2]); // => 42
// Factorial system
pack([1, 3, 0, 0, 0], [5, 4, 3, 2, 1]); // => 42
And now backwards:
unpack(42, [10, 10]); // => [4, 2]
unpack(42, [5, 4, 3, 2, 1]); // => [1, 3, 0, 0, 0]
This is so beautiful. Now let's apply this parametric number system to the problem of permutations. We'll consider length 2 permutations of A, B, C, D. What's the total number of them? Let's see: first we draw one of the 4 items, then one of the remaining 3, that's 4 * 3 = 12 ways to draw 2 items. These 12 ways can be packed into integers [0..11]. So, let's pretend we've packed them already, and try unpacking:
for (var i = 0; i < 12; i++) {
console.log(unpack(i, [4, 3]));
}
// [0, 0], [0, 1], [0, 2],
// [1, 0], [1, 1], [1, 2],
// [2, 0], [2, 1], [2, 2],
// [3, 0], [3, 1], [3, 2]
These numbers represent choices, not indexes in the original array. [0, 0] doesn't mean taking A, A, it means taking item #0 from A, B, C, D (that's A) and then item #0 from the remaining list B, C, D (that's B). And the resulting permutation is A, B.
Another example: [3, 2] means taking item #3 from A, B, C, D (that's D) and then item #2 from the remaining list A, B, C (that's C). And the resulting permutation is D, C.
This mapping is called Lehmer code. Let's map all these Lehmer codes to permutations:
AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC
That's exactly what we need. But if you look at the unpack function you'll notice that it produces digits from right to left (to reverse the actions of pack). The choice from 3 gets unpacked before the choice from 4. That's unfortunate, because we want to choose from 4 elements before choosing from 3. Without being able to do so we have to compute the Lehmer code first, accumulate it into a temporary array, and then apply it to the array of items to compute the actual permutation.
But if we don't care about the lexicographic order, we can pretend that we want to choose from 3 elements before choosing from 4. Then the choice from 4 will come out from unpack first. In other words, we'll use unpack(n, [3, 4]) instead of unpack(n, [4, 3]). This trick allows to compute the next digit of Lehmer code and immediately apply it to the list. And that's exactly how nth_permutation() works.
One last thing I want to mention is that unpack(i, [4, 3]) is closely related to the factorial number system. Look at that first tree again, if we want permutations of length 2 without duplicates, we can just skip every second permutation index. That'll give us 12 permutations of length 4, which can be trimmed to length 2.
for (var i = 0; i < 12; i++) {
var lehmer = unpack(i * 2, [4, 3, 2, 1]); // Factorial number system
console.log(lehmer.slice(0, 2));
}
It depends on the way you "sort" your permutations (lexicographic order for example).
One way to do it is the factorial number system, it gives you a bijection between [0 , n!] and all the permutations.
Then for any number i in [0,n!] you can compute the ith permutation without computing the others.
This factorial writing is based on the fact that any number between [ 0 and n!] can be written as :
SUM( ai.(i!) for i in range [0,n-1]) where ai <i
(it's pretty similar to base decomposition)
for more information on this decomposition, have a look at this thread : https://math.stackexchange.com/questions/53262/factorial-decomposition-of-integers
hope it helps
As stated on this wikipedia article this approach is equivalent to computing the lehmer code :
An obvious way to generate permutations of n is to generate values for
the Lehmer code (possibly using the factorial number system
representation of integers up to n!), and convert those into the
corresponding permutations. However the latter step, while
straightforward, is hard to implement efficiently, because it requires
n operations each of selection from a sequence and deletion from it,
at an arbitrary position; of the obvious representations of the
sequence as an array or a linked list, both require (for different
reasons) about n2/4 operations to perform the conversion. With n
likely to be rather small (especially if generation of all
permutations is needed) that is not too much of a problem, but it
turns out that both for random and for systematic generation there are
simple alternatives that do considerably better. For this reason it
does not seem useful, although certainly possible, to employ a special
data structure that would allow performing the conversion from Lehmer
code to permutation in O(n log n) time.
So the best you can do for a set of n element is O(n ln(n)) with an adapted data structure.
Here's an algorithm to convert between permutations and ranks in linear time. However, the ranking it uses is not lexicographic. It's weird, but consistent. I'm going to give two functions, one that converts from a rank to a permutation, and one that does the inverse.
First, to unrank (go from rank to permutation)
Initialize:
n = length(permutation)
r = desired rank
p = identity permutation of n elements [0, 1, ..., n]
unrank(n, r, p)
if n > 0 then
swap(p[n-1], p[r mod n])
unrank(n-1, floor(r/n), p)
fi
end
Next, to rank:
Initialize:
p = input permutation
q = inverse input permutation (in linear time, q[p[i]] = i for 0 <= i < n)
n = length(p)
rank(n, p, q)
if n=1 then return 0 fi
s = p[n-1]
swap(p[n-1], p[q[n-1]])
swap(q[s], q[n-1])
return s + n * rank(n-1, p, q)
end
The running time of both of these is O(n).
There's a nice, readable paper explaining why this works: Ranking & Unranking Permutations in Linear Time, by Myrvold & Ruskey, Information Processing Letters Volume 79, Issue 6, 30 September 2001, Pages 281–284.
http://webhome.cs.uvic.ca/~ruskey/Publications/RankPerm/MyrvoldRuskey.pdf
Here is a short and very fast (linear in the number of elements) solution in python, working for any list of elements (the 13 first letters in the example below) :
from math import factorial
def nthPerm(n,elems):#with n from 0
if(len(elems) == 1):
return elems[0]
sizeGroup = factorial(len(elems)-1)
q,r = divmod(n,sizeGroup)
v = elems[q]
elems.remove(v)
return v + ", " + ithPerm(r,elems)
Examples :
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m']
ithPerm(0,letters[:]) #--> a, b, c, d, e, f, g, h, i, j, k, l, m
ithPerm(4,letters[:]) #--> a, b, c, d, e, f, g, h, i, j, m, k, l
ithPerm(3587542868,letters[:]) #--> h, f, l, i, c, k, a, e, g, m, d, b, j
Note: I give letters[:] (a copy of letters) and not letters because the function modifies its parameter elems (removes chosen element)
The following code computes the kth permutation for given n.
i.e n=3.
The various permutations are
123
132
213
231
312
321
If k=5, return 312.
In other words, it gives the kth lexicographical permutation.
public static String getPermutation(int n, int k) {
char temp[] = IntStream.range(1, n + 1).mapToObj(i -> "" + i).collect(Collectors.joining()).toCharArray();
return getPermutationUTIL(temp, k, 0);
}
private static String getPermutationUTIL(char temp[], int k, int start) {
if (k == 1)
return new String(temp);
int p = factorial(temp.length - start - 1);
int q = (int) Math.floor(k / p);
if (k % p == 0)
q = q - 1;
if (p <= k) {
char a = temp[start + q];
for (int j = start + q; j > start; j--)
temp[j] = temp[j - 1];
temp[start] = a;
}
return k - p >= 0 ? getPermutationUTIL(temp, k - (q * p), start + 1) : getPermutationUTIL(temp, k, start + 1);
}
private static void swap(char[] arr, int j, int i) {
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static int factorial(int n) {
return n == 0 ? 1 : (n * factorial(n - 1));
}
It is calculable. This is a C# code that does it for you.
using System;
using System.Collections.Generic;
namespace WpfPermutations
{
public class PermutationOuelletLexico3<T>
{
// ************************************************************************
private T[] _sortedValues;
private bool[] _valueUsed;
public readonly long MaxIndex; // long to support 20! or less
// ************************************************************************
public PermutationOuelletLexico3(T[] sortedValues)
{
if (sortedValues.Length <= 0)
{
throw new ArgumentException("sortedValues.Lenght should be greater than 0");
}
_sortedValues = sortedValues;
Result = new T[_sortedValues.Length];
_valueUsed = new bool[_sortedValues.Length];
MaxIndex = Factorial.GetFactorial(_sortedValues.Length);
}
// ************************************************************************
public T[] Result { get; private set; }
// ************************************************************************
/// <summary>
/// Return the permutation relative to the index received, according to
/// _sortedValues.
/// Sort Index is 0 based and should be less than MaxIndex. Otherwise you get an exception.
/// </summary>
/// <param name="sortIndex"></param>
/// <param name="result">Value is not used as inpu, only as output. Re-use buffer in order to save memory</param>
/// <returns></returns>
public void GetValuesForIndex(long sortIndex)
{
int size = _sortedValues.Length;
if (sortIndex < 0)
{
throw new ArgumentException("sortIndex should be greater or equal to 0.");
}
if (sortIndex >= MaxIndex)
{
throw new ArgumentException("sortIndex should be less than factorial(the lenght of items)");
}
for (int n = 0; n < _valueUsed.Length; n++)
{
_valueUsed[n] = false;
}
long factorielLower = MaxIndex;
for (int index = 0; index < size; index++)
{
long factorielBigger = factorielLower;
factorielLower = Factorial.GetFactorial(size - index - 1); // factorielBigger / inverseIndex;
int resultItemIndex = (int)(sortIndex % factorielBigger / factorielLower);
int correctedResultItemIndex = 0;
for(;;)
{
if (! _valueUsed[correctedResultItemIndex])
{
resultItemIndex--;
if (resultItemIndex < 0)
{
break;
}
}
correctedResultItemIndex++;
}
Result[index] = _sortedValues[correctedResultItemIndex];
_valueUsed[correctedResultItemIndex] = true;
}
}
// ************************************************************************
/// <summary>
/// Calc the index, relative to _sortedValues, of the permutation received
/// as argument. Returned index is 0 based.
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public long GetIndexOfValues(T[] values)
{
int size = _sortedValues.Length;
long valuesIndex = 0;
List<T> valuesLeft = new List<T>(_sortedValues);
for (int index = 0; index < size; index++)
{
long indexFactorial = Factorial.GetFactorial(size - 1 - index);
T value = values[index];
int indexCorrected = valuesLeft.IndexOf(value);
valuesIndex = valuesIndex + (indexCorrected * indexFactorial);
valuesLeft.Remove(value);
}
return valuesIndex;
}
// ************************************************************************
}
}
If you store all the permutations in memory, for example in an array, you should be able to bring them back out one at a time in O(1) time.
This does mean you have to store all the permutations, so if computing all permutations takes a prohibitively long time, or storing them takes a prohibitively large space then this may not be a solution.
My suggestion would be to try it anyway, and come back if it is too big/slow - there's no point looking for a "clever" solution if a naive one will do the job.

How to find the % of a value on a Y axis of a LOG graph?

Wow, this one is though!
I'm trying to find in PHP the % of a value relative to the Y axis. If we refer to this graph : http://en.wikipedia.org/wiki/Semi-log_graph (2009 outbreak of influenza A), let's say that I want to find what % is a value "256" on the chart.
Visually, it's easy : it's a bit more than a 1/3 or 33%. If we look at the 1024 value, it's around 50% of the height of the Y axis. 131072 would be 100%.
So how do I calculate this with PHP?
Let's take this graph and take X = day 0 and Y = 256. What is 256 as a % of Y ?
Thanks a lot to anyone can compute this baby :)
percent = 100 * ( log(y) - log(y1) ) / ( log(y2) - log(y1) )
where
y = value
y1 = smallest value in y-axis
y2 = largest value in y-axis.
when y1 = 1.0 then you can simplify the other answers given here (since log(1)=0 by definition)
percent = 100 * log(y)/log(y2)
Note that not all log charts have 1.0 as the lowest value.
ln(131072) = 11.783 is 100%
ln(1024) = 6.931 is 58.824%
in PHP, that function is called log()
no need to set the base, as you are dividing them to find the relative value.
Alex got it, but to generalize for you and PHPize
logPercent = log(x) / log(top) * 100;
If you take the log of your max y value (131072 in your case) and the log of your y value (256), you end up with a height and a y value which is linear in relation to your drawn axis. you can divide them to get a decimal of the height and times by 100 for %:
using log base 2 seen as it gives integers (though any base should be fine).
log(256) / log(131072) = 8/17 = 0.47 = 47%
in php:
(log(256, 2) / log(131072, 2))*100;

Adding number should depend on current value

I want to add a number to a var. This number should be bigger when var is small and smaller when var is big. I have calculate the optimum values: when var=1, function should add 125. When var=50 function should add 420. I was thinking about sin function, but I have no idea how to "personalize" this function to work with it. (I am using php)
For a function with the form:
f[x_] := x + Sin[y*x + z]
Subject to the constraints
f[1] == 1 + 125 && f[50] == 50 + 420
You have
{{y -> 1/49 (-ArcSin[125] + ArcSin[420]),
z -> 1/49 (50 ArcSin[125] - ArcSin[420])}}
which is approximately
{{y -> 0. - 0.0247338 I, z -> 1.5708 - 5.49671 I}}
Between 0 and 70, this gives:
An approximate function, using only real values, is:
f(x) = x + 121.94629730754633 cosh(0.02473378688005212 x) +
121.94219707312345 sinh(0.02473378688005212 x)
The sine function is periodic and probably not suitable for the task.
Your example is not clear: you say add 'bigger number when var is small and smaller number when var is bigger', but add 125 to 1 and 420 to 50, which contradicts the text.
One possibility is the reciprocal function - it meets your stated requirements but not your example requirements.
Given just 2 data points, we can deduce a linear relationship:
y = 125 + (420 - 125) / (50 - 1) * (x - 1)
which is approximately:
y = 119 + 6x
Check:
x = 1; y = 125
x = 50; y = 419
The approximate factor 6 is a rounding of 6.0204081632 ... which is an intriguing sequence in the fractional part.
Try to make a linear equation projection.
VarAdd = Var*Slop+Start; eq [1]
125=1*Slop+Start ---1
420=50*Slop+Start –2
Solve Slop and Start then apply eq[1] any time.

Categories