How do I convert UISlider value without changing current minimum and maximum slider value - ios

I have 2 sliders, both sliders have a minimum and maximum value set to 0 and 1. In the pic, they simulate changing ramp values at a maximum of 300 total frames combined.
For the first slider, I get the range of 0-150 frames correctly with
int selectedFrameCount = 300;
int currentSelectedFrameValue = sender.value * (selectedFrameCount/2);
I'd like to know how to get a range of 150-300 frames with the second slider without changing the minimum and maximum UISlider values because I need those values for a separate calculation.
For a separate function, I'll need to convert that value back to from selected 150-300 value into a float based on the 0-1 value selected.
example: 285 = x * (300/2) + 150;

Isn't it as simple as
int currentSelectedFrameValue = (sender == firstSlider ? 0 : selectedFrameCount/2)
+ sender.value * (selectedFrameCount/2);
?

You have to imagine your calc as a function (it is, so you haven't to imagine it :D )
y is the int you want
x is the sender.vale
y(x) = x * (selectedFrame/2)
If you want to translate your line on y-axis by selectedFrame/2 you just have to add it to as q value on linear equation y(x) = mx + q
So, the solution is
int value = sender.value * (selectedFrame/2) + (selectedFrame/2)
To convert the int value into a float value in 0-1 range, use this
multipliedMaxValue = selectedFrame
multipliedSelectedValue = value
multipliedMaxValue : 1 = multipliedSelectedValue : x
if you want x, just do
float toRangeValue = (float)multipliedSelectedValue / (float)multipliedMaxValue;

Related

Generating a Histogram by Harmonic Number

I am trying to create a program in GNU Octave to draw a histogram showing the fundamental and harmonics of a modified sinewave (the output from an SCR dimmer, which consists of a sinewave which is at zero until part way through the wave).
I've been able to generate the waveform and perform FFT to get a set of Frequency vs Amplitude points, however I am not sure how to convert this data into bins suitable for generating a histogram.
Sample code and an image of what I'm after below - thanks for the help!
clear();
vrms = 120;
freq = 60;
nCycles = 2;
level = 25;
vpeak = sqrt(2) * vrms;
sampleinterval = 0.00001;
num_harmonics = 10
disp("Start");
% Draw the waveform
x = 0 : sampleinterval : nCycles * 1 / freq; % time in sampleinterval increments
dimmed_wave = [];
undimmed_wave = [];
for i = 1 : columns(x)
rad_value = x(i) * 2 * pi * freq;
off_time = mod(rad_value, pi);
on_time = pi*(100-level)/100;
if (off_time < on_time)
dimmed_wave = [dimmed_wave, 0]; % in the dimmed period, value is zero
else
dimmed_wave = [dimmed_wave, sin(rad_value)]; % when not dimmed, value = sine
endif
undimmed_wave = [undimmed_wave, sin(rad_value)];
endfor
y = dimmed_wave * vpeak; % calculate instantaneous voltage
undimmed = undimmed_wave * vpeak;
subplot(2,1,1)
plot(x*1000, y, '-', x*1000, undimmed, '--');
xlabel ("Time (ms)");
ylabel ("Voltage");
% Fourier Transform to determine harmonics
subplot(2,1,2)
N = length(dimmed_wave); % number of points
fft_vals = abs(fftshift(fft(dimmed_wave))); % perform fft
frequency = [ -(ceil((N-1)/2):-1:1) ,0 ,(1:floor((N-1)/2)) ] * 1 / (N *sampleinterval);
plot(frequency, fft_vals);
axis([0,400]);
xlabel ("Frequency");
ylabel ("Amplitude");
You know your base frequency (fundamental tone), let's call it F. 2*F is the second harmonic, 3*F the third, etc. You want to set histogram bin edges halfway between these: 1.5*F, 2.5*F, etc.
You have two periods in your input signal, therefore your (integer) base frequency is k=2 (the value at fft_vals[k+1], the first peak in your plot). The second harmonic is at k=4, the third one at k=6, etc.
So you would set your bins edges at k = 1:2:end.
In general, this would be k = nCycles/2:nCycles:end.
You can compute your bar graph according to our computed bin edges as follows:
fft_vals = abs(fft(dimmed_wave));
nHarmonics = 9;
edges = nCycles/2 + (0:nHarmonics)*nCycles;
H = cumsum(fft_vals);
H = diff(H(edges));
bar(1:nHarmonics,H);

Getting Pixel value in the image

I am calculating the RGB values of pixels in my captured photo. I have this code
func getPixelColorAtLocation(context: CGContext, point: CGPoint) -> Color {
self.context = createARGBBitmapContext(imgView.image!)
let data = CGBitmapContextGetData(context)
let dataType = UnsafePointer<UInt8>(data)
let offset = 4 * ((Int(imageHeight) * Int(point.x)) + Int(point.y))
var color = Color()
color.blue = dataType[offset]
color.green = dataType[offset + 1]
color.red = dataType[offset + 2]
color.alpha = dataType[offset + 3]
color.point.x = point.x
color.point.y = point.y
But I am not sure what this line means in the code.
let offset = 4 * ((Int(imageHeight) * Int(point.x)) + Int(point.y))
Any help??
Thanks in advance
Image is the set of pixels. In order to get the pixel at (x,y) point, you need to calculate the offset for that set.
If you use dataType[0], it has no offset 'cos it points to the place where the pointer is. If you used dataType[10], it would mean you took 10-th element from the beginning where the pointer is.
Due to the fact, we have RGBA colour model, you should multiply by 4, then you need to get what offset by x (it will be x), and by y (it will be the width of the image multiplied by y, in order to get the necessary column) or:
offset = x + width * y
// offset, offset + 1, offset + 2, offset + 3 <- necessary values for you
Imagine, like you have a long array with values in it.
It will be clear if you imagine the implementation of two-dimensional array in the form of one-dimensional array. It would help you, I hope.

Random number between two ranges

I'm trying to generate a random number between two ranges in Objective-C.
For example between [-50;-30] and [30,50].
I achieved to do it between [-50,50] but I need to eliminate all the values between [-30,30].
int rads = -50 + arc4random() % (50 - (-50));
Thanks for your help.
To build on the previous answer (which has been removed):
use arc4random_uniform
use correct upper bounds and correct arithmetics
Regarding 1: arc4random_uniform(50) will yield a number between 0 and 49 inclusive. It will yield that value with a correct unfirom distribution. Using only arc4random % something introduces modulo bias.
Regarding 2: You are trying not to retrieve 40 values but 42 since you want to be able to retrieve the upper a nd the lower bound values as well. If we simplify the bounds we can see the error better, assume [-5;-3] and [3;5]: you want the numbers -5,-4,-3,3,4,5 six values, not 4.
Solution:
int rads = arc4random_uniform(42) - 20; // values between -20 and 21 inclusive, 42 different numbers
if (rads <= 0) { // subtract from the lower 21 values [-20;0]
rads = rads - 30; // [-50;-30]
} else { // add to the upper 21 values [1;21]
rads = rads + 29; // [30;50]
}
More general for symmetric upper and lower bounds
int lower = 30;
int upper = 50;
int diff = upper - lower;
int rads = arc4random_uniform((diff + 1) * 2) - diff; // values between -diff and (diff+1) inclusive, ((diff+1)*2) different numbers
if (rads <= 0) { // subtract from the lower (diff+1) values [-diff;0]
rads = rads - lower; // [-upper;-lower]
} else { // add to the upper 21 values [1;diff+1]
rads = rads + lower - 1; // [lower;upper]
}
Note that you can simplfy the code a bit by moving the conditional substraction up to the initial rads calculation and changing the later addition and the condition for adding. BUT that would make the code a bit less readable and intutive.
One thing to try would be choosing randomly either 1 or -1. Then multiplying that by another random number between 30-50 would work.

Formatting an integer value

Im obtaining an int value from UITextField [self.dbRef.text intValue];
I want to then format that value so I can add a decimal place that precceds the number ie. If [self.dbRef.text intValue]; returns 4 i need that value to be 0.04
So far I have tried various ways including
float Y = ([self.dbRef.text intValue]/100);
slice.value = Y;
NSLog(#"float Y value = %f",Y);
returns zero
NSString* formatedTotalApplianceString = [NSString stringWithFormat:#"0.%#", self.dbRef.text];
NSLog(#"formated string = %#",formatedTotalApplianceString);
int totalAppliances = [formatedTotalApplianceString intValue];
NSLog(#"Resulting int value = %d",[formatedTotalApplianceString intValue]);
slice.value = totalAppliances;
NSLog(#"total appliances int value = %d",totalAppliances);
returns zero
You're doing an integer division, so the 0 value is correct in that context as integers cannot represent fractions (unless you're doing fixed point arithmetics, but that's a different can of worms). You need to do a floating point division, for example:
float Y = ([self.dbRef.text floatValue]/100.0f);
Either the [self.dbRef.text floatValue] or the 100.0f will turn this into a float division, because if the other side would be an int it would automatically get casted to a float. But the "best" way is to have both values of the same type.
Change
float Y = [self.dbRef.text intValue]/100;
to
float Y = ((float)[self.dbRef.text intValue])/100;
in your first variant.
Dividing int by int returns you int result even if then you assign it to float. 4/100 = 0 in such case.
The problem with [self.dbRef.text intValue]/100 is that it's an integer division. It drops the fraction. One way to work around it is to divide by 100.0:
[self.dbRef.text intValue]/100.0
However, this is not the most efficient way of doing it if all you need is adding a zero in front of a fraction: you could avoid float altogether by padding your printed int to two positions with leading zeros:
// If text is 4, the code below prints 0.04
NSLog(#"0.%02d", [self.dbRef.text intValue]);
The first code returns zero because you are performing an integer division, which produces an integer result. You should cast the value to a float.
The second code also returns zero because you're asking for the intValue of a floating point value. So the decimal part will be discarded.
NSString has also a floatValue method, you should use it to get a floating value. Once divided by 100 you will still have a floating point value (in a division if the quotient or the dividend is a float and the other an integer, the integer gets promoted to float):
float Y = ([self.dbRef.text floatValue]/100);
slice.value = Y;

Truncating Actionscript Number

I have a number in actionscript, arrived at via some arbitrary math:
var value:Number = 45 * (1 - (1 /3));
trace(value);//30.00000000004
Now, I would like to take the ceiling of this number, except in cases where the amount it is greater than the next lower integer is smaller than some epsilon. In the above example, I really want to round to 30, but only in the case where I know I'm getting a rounding error:
Math.ceil(value); //I want 30, but get 31
Math.ceil(30.1); //In this case, it's reasonable to get 31
Is there an elegant way to truncate a Number in actionscript? Or easily discard any part of the number that is less than some epsilon?
Is this method is of any help to you?
var precision:int = 4;
var isActualCeilingValRequred:Boolean;
var thresholdValForCeiling:int = 100;
private function getCeilingValue(num:Number):Number
{
var tempNum = num * Math.pow(10, precision);
var decimalVal = tempNum % Math.pow(10, precision);
if(decimalVal < thresholdValForCeiling) {
return Math.floor(num);
} else {
return Math.Ceil(num);
}
}
var value:Number = 45 * (1 - (1 /3));
trace(value);//30.00000000004
// Play with arbitraryPrecision until you are satisfied with
// the accuracy of your results
var arbitraryPrecision:int = 3;
var fixed:Number = value.toFixed(arbitraryPrecision);
trace(Math.ceil(fixed));
The basic way to round a number to a specified number of fractional digits is to multiply the number to 10^DIGITS to shift the decimal point DIGITS digits to the left, perform the rounding, and divide by the same 10^DIGITS to shift the decimal point back to the right.
var value:Number = 45 * (1 - (1 / 3));
trace(value); // 30.000000000000004
trace(Math.ceil(value)); // 31
// Round the number to 13 decimal digits.
const POWER:Number = 1e13;
value = Math.round(value * POWER) / POWER;
trace(value); // 30
// Compute number's ceiling.
value = Math.ceil(value);
trace(value); // 30`
It works for your example, but there's a big gotcha. If you change your value to be 450 * (1 - (1 / 3));, your original problem will appear again. Now to get rid of it, you would have to round to 12 decimal digits. Basically, the significand of a double-precision format (Number) can hold about 15 significant digits. This means as the value increases by a factor of ten, the decimal points moves to the left and that last "4" digit you want to get rid of becomes closer and closer to the decimal point. So the code becomes more complicated.
var value:Number = 450 * (1 - (1 / 3));
trace(value); // 30.000000000000004
trace(Math.ceil(value)); // 31
var exp:Number = Math.floor(Math.log(Math.abs(value)) * Math.LOG10E);
trace('exp=' + exp); // exp=2
const POWER:Number = Math.pow(10, 14 - exp);
value *= POWER;
trace(value); // 300000000000000.06
value = Math.round(value);
trace(value); // 300000000000000
value /= POWER;
trace(value); // 300
As you can see, it now works regardless of the value's magnitude.
First, I find the number's exponent by taking a base-10 logarithm of the number's absolute value, then rounding it down. If you calculate a = value * Math.pow(10, exp);, then value could be represented as a * 10^b, where (1 ≤ |a| < 10), known as normalized scientific notation. But that's not what we're doing here. Now that we know how many digits are on the left of the decimal point, we will shift the decimal point right, but not too far, to keep one 0 and this error digit we want to get rid of, on the right side of the decimal point. So, multiply by 10^(14-exp), round, then divide by the same power.

Resources