I'm using the jquery ui slider for zooming. It's supposed to zoom from 25% to %500, and about half of the range is used for the first %100 of the size.
The slider has values from 1 to 100. I need some function that can be used to calculate zooming based on the slider value, e.g.
function getZoom(sliderVal) {
//return number from 25 to 500
}
Any suggestions?
I think it's better for the user if you provide exponential fitting.
Javascript has Math.pow(a,b) which calculates ab.
The setting makes more sense if you map range [0,100] to [25%,400%], because then 50 is at the exact midpoint and can be made easily to map too 100%. 50 points on the slider then correspond to division or multiplication by four, so you can set
scaling = Math.pow(2,(slider - 50) / 25);
So then you get the mapping below:
slider scaling
------------------
0 2**-2 = 1/4 = 25%
25 2**-1 = 1/2 = 50%
50 2**0 = 1 = 100%
75 2**1 = 2 = 200%
100 2**2 = 4 = 400%
Now I see that this doesn't answer your question completely because your scale is [1,100] instead of [0,100], and you want to reach 500% instead of 400%.
To get there, you can first normalize the slider:
slider_n = (slider - 1) * (100/99);
(this maps [1,100] to [0,100]), and then, if you want, multiply positive values of the exponent by (log 5)/(log 4) so that your scale ends at 500%, i.e.
exp = (slider_n - 50) / 25.0;
if (exp > 0) exp = exp * Math.log(5)/Math.log(4);
scaling = Math.pow(2,exp);
Basically you want to rescale something from 1-100 to 25-500.
100-1 = 99
500-25 = 475
so that's your scaling factor - every point of difference on your slider is 475/99 points of difference on the zoom.
And the fixed offset is just 1 and 25, giving you a simple formula of:
f( slider_value ) =
( slider_value - 1 ) * ( 475 / 99 ) + 25
Of course, if you want to generalize, two scales from (a,b) to (c,d):
f( slider_value ) =
( slider_value - a ) * ( ( d - c ) / ( b - a ) ) + c
Now, if you want to do some kind of half-half thing, you can just use the above formula to divide the portions you want, and call different functions varying on the slider's value. As long as they are continuous (the values are the same for the border cases) it should feel fine.
For your case, try mapping 1-50.5 to 25%-100%, 50.5-100 to 100%-500%.
Related
Code pen (available online, have not made any changes here)
https://codepen.io/SteveJRobertson/pen/zxEwrK
Javascript
var cube = document.getElementById('cube');
var min = 1;
var max = 24;
cube.onclick = function() {
var xRand = getRandom(max, min);
var yRand = getRandom(max, min);
cube.style.webkitTransform = 'rotateX('+xRand+'deg)
rotateY('+yRand+'deg)';
cube.style.transform = 'rotateX('+xRand+'deg)
rotateY('+yRand+'deg)';
}
function getRandom(max, min) {
return (Math.floor(Math.random() * (max-min)) + min) *
90;
}
What I want-
after the dice finishes transition, it finishes with a face facing you. Is there a way to get which face this is?(i am considering this face as the output of the dice throw)
What I did-
I could not find the solution. Do after the dice finishes transition, I force it to another transition I want so that it finishes where I want it to. (
#cube.show-front {
transform: translateZ(-100px) rotateY( 0deg);
}
will make the cube land on its front side
You could have some complex matrix maths to figure that out but a quick look at how things are done can give you a simple solution.
The first thing to make sure to note is the initial position of all the faces. The faces are not positioned like on a real dice (the sum of opposite faces would equal 7, e.g. 1 opposed to 6).
Another thing is that the rotation only happens on 2 axes, each by a multiple of 90 degrees (a quarter of turn). And 4 quarters of turns (i.e. 1 full turn) is equivalent to no turn at all, so it is a repeating pattern and we can work with modulos.
Now for the actual rotation, I find it easier to work with fixed origins (not moving with the object), which means you need to read the CSS transform values from right to left.
First you are rotating the cube around the Y axis (front face moving towards the left / right) a certain number of times.
Once that is done you are rotating the cube around the X axis (front face moving up /down).
If you try to picture that you might notice that no matter what we do during the first step the top face will stay at the top (5 here) and the bottom one at the bottom (6 here). Which means with the second and last rotation we can easily tell if the cube finished on 5, 6, or a different number.
For the other cases this is just a matter of picking the correct value based on the first Y rotation (while not forgetting that a 180 degrees rotation on the X axis will show the opposite face).
// modulo not giving negative results - see https://stackoverflow.com/q/4467539/1336843
function mod(n, m) {
return ((n % m) + m) % m;
}
function getResult(rotX, rotY) {
let countX = mod(rotX / 90, 4);
if (countX === 1) {
// Bottom face
return 6;
}
if (countX === 3) {
// Top face
return 5;
}
// We add countX here to correctly offset in case it is a 180 degrees rotation
// It can be 0 (no rotation) or 2 (180 degrees)
let countY = mod(rotY / 90 + countX, 4);
// Faces order
return [1, 4, 2, 3][countY];
}
Fork of the pen logging the result to the console: codepen
You will notice that this shuffling method will not give each result an equal probability. The top and bottom faces (5 and 6) will be more likely to appear (1 time out of 4 each, while all the other faces will appear 1 time out of 8).
I have a logarithmic scale going from 0 to 100:
0.00
0.10
1.00
10.00
100.00
I need to make a pie chart which has 4 quarters.
the first is going from 0 to 0.10
the second is from 0.10 to 1 etc.etc.
So if I have the value 25, it should be calculated which percentage this is in the logarithmic scale. Considering the scale it should end up somewhere in the last quarter of the chart.
Unfortunately my understanding of Maths does not reach this far ;)
Could you help out and tell me where to start.
I thought of looking at each quarter as a 100% piece, and then calculate where this might be in this quarter..
per example:
32 > 10 so it should be in the last quarter (percentage wise above 75%)
So in this last quarter 32 will be in:
((32-10) x 100) / (100 - 10) = 24.44% in this quarter
Making this 24.44 / 4 = 6.11% over 4 quarters and thus 75 + 6.11 = 81.11% of the whole chart.
Now this would work, but I am looking for a shorter and simpler way of calculating this.
Can you please help out.
This is surely a maths question about plotting values on a logarithmic
scale, and not really anything to do with JavaScript in particular or
programming in general. Anyhow ...
You need to decide on a minimum value, since the logarithm of zero is
undefined. Once you have your maximum and minimum logarithms, you can
scale your values as you wish. Slightly ontopic: JavaScript has
Math.log10 in more up-to-date engines (and can be readily
defined if not, e.g. as in #NinaScholz's answer or using the polyfill here).
var minval = 0.01,
maxval = 100,
minlog = Math.log10(minval),
maxlog = Math.log10(maxval),
range = maxlog - minlog,
lineartolog = function(n){
return (Math.log10(n) - minlog) / range;
},
logplots = [
0.01,
0.1,
1,
3.2,
10,
32,
75,
100
].map(lineartolog);
document.body.innerHTML = '<pre>' + logplots + '</pre>';
Adjust as required for percentages, radians, etc.
Consideration:
q0 q1 q2 q3
01234567890123456789012345678901234567890
| | | | |
0.01 0.1 1 10 100
0.32 3.2 32
because log10(32) = 1.505 = 1 + 0.505
because log10(3.2) = 0.505 = 0 + 0.505
because log10(0.32) = -0,495 = -1 + 0.505
^ ^
quadrant after adding 2 amount to fill
together, fill is the amount in %:
function log10(f) {
return Math.log(f) / Math.log(10);
}
function getValue(v) {
var l = log10(v),
quadrant = Math.floor(l) + 2,
fill = (l - Math.floor(l)) * 100;
return { quadrant: quadrant, fill: fill };
}
console.log('0.32', getValue(0.32));
console.log('3.2', getValue(3.2));
console.log('32', getValue(32));
BACKGROUND:
The app allows users to upload a photo of themselves and then place a pair of glasses over their face to see what it looks like. For the most part, it is working fine. After the user selects the location of the 2 pupils, I auto zoom the image based on the ratio between the distance of the pupils and then already known distance between the center points of the glasses. All is working fine there, but now I need to automatically place the glasses image over the eyes.
I am using KinectJS, but the problem is not with regards to that library or javascript.. it is more of an algorithm requirement
WHAT I HAVE TO WORK WITH:
Distance between pupils (eyes)
Distance between pupils (glasses)
Glasses width
Glasses height
Zoom ratio
SOME CODE:
//.. code before here just zooms the image, etc..
//problem is here (this is wrong, but I need to know what is the right way to calculate this)
var newLeftEyeX = self.leftEyePosition.x * ratio;
var newLeftEyeY = self.leftEyePosition.y * ratio;
//create a blue dot for testing (remove later)
var newEyePosition = new Kinetic.Circle({
radius: 3,
fill: "blue",
stroke: "blue",
strokeWidth: 0,
x: newLeftEyeX,
y: newLeftEyeY
});
self.pointsLayer.add(newEyePosition);
var glassesWidth = glassesImage.getWidth();
var glassesHeight = glassesImage.getHeight();
// this code below works perfect, as I can see the glasses center over the blue dot created above
newGlassesPosition.x = newLeftEyeX - (glassesWidth / 4);
newGlassesPosition.y = newLeftEyeY - (glassesHeight / 2);
NEEDED
A math genius to give me the algorithm to determine where the new left eye position should be AFTER the image has been resized
UPDATE
After researching this for the past 6 hours or so, I think I need to do some sort of "translate transform", but the examples I see only allow setting this by x and y amounts.. whereas I will only know the scale of the underlying image. Here's the example I found (which cannot help me):
http://tutorials.jenkov.com/html5-canvas/transformation.html
and here is something which looks interesting, but it is for Silverlight:
Get element position after transform
Is there perhaps some way to do the same in Html5 and/or KinectJS? Or perhaps I am going down the wrong road here... any ideas people?
UPDATE 2
I tried this:
// if zoomFactor > 1, then picture got bigger, so...
if (zoomFactor > 1) {
// if x = 10 (for example) and if zoomFactor = 2, that means new x should be 5
// current x / zoomFactor => 10 / 2 = 5
newLeftEyeX = self.leftEyePosition.x / zoomFactor;
// same for y
newLeftEyeY = self.leftEyePosition.y / zoomFactor;
}
else {
// else picture got smaller, so...
// if x = 10 (for example) and if zoomFactor = 0.5, that means new x should be 20
// current x * (1 / zoomFactor) => 10 * (1 / 0.5) = 10 * 2 = 20
newLeftEyeX = self.leftEyePosition.x * (1 / zoomFactor);
// same for y
newLeftEyeY = self.leftEyePosition.y * (1 / zoomFactor);
}
that didn't work, so then I tried an implementation of Rody Oldenhuis' suggestion (thanks Rody):
var xFromCenter = self.leftEyePosition.x - self.xCenter;
var yFromCenter = self.leftEyePosition.y - self.yCenter;
var angle = Math.atan2(yFromCenter, xFromCenter);
var length = Math.hypotenuse(xFromCenter, yFromCenter);
var xNew = zoomFactor * length * Math.cos(angle);
var yNew = zoomFactor * length * Math.sin(angle);
newLeftEyeX = xNew + self.xCenter;
newLeftEyeY = yNew + self.yCenter;
However, that is still not working as expected. So, I am not sure what the issue is currently. If anyone has worked with KinectJS before and has an idea of what the issue may be, please let me know.
UPDATE 3
I checked Rody's calculations on paper and they seem fine, so there is obviously something else here messing things up.. I got the coordinates of the left pupil at zoom factors 1 and 2. With those coordinates, maybe someone can figure out what the issue is:
Zoom Factor 1: x = 239, y = 209
Zoom Factor 2: x = 201, y = 133
OK, since it's an algorithmic question, I'm going to keep this generic and only write pseudo code.
I f I understand you correctly, What you want is the following:
Transform all coordinates such that the origin of your coordinate system is at the zoom center (usually, central pixel)
Compute the angle a line drawn from this new origin to a point of interest makes with the positive x-axis. Compute also the length of this line.
The new x and y coordinates after zooming are defined by elongating this line, such that the new line is the zoom factor times the length of the original line.
Transform the newly found x and y coordinates back to a coordinate system that makes sense to the computer (e.g., top left pixel = 0,0)
Repeat for all points of interest.
In pseudo-code (with formulas):
x_center = image_width/2
y_center = image_height/2
x_from_zoom_center = x_from_topleft - x_center
y_from_zoom_center = y_from_topleft - y_center
angle = atan2(y_from_zoom_center, x_from_zoom_center)
length = hypot(x_from_zoom_center, y_from_zoom_center)
x_new = zoom_factor * length * cos(angle)
y_new = zoom_factor * length * sin(angle)
x_new_topleft = x_new + x_center
y_new_topleft = y_new + y_center
Note that this assumes the number of pixels used for length and width stays the same after zooming. Note also that some rounding should take place (keep everything double precision, and only round to int after all calculations)
In the code above, atan2 is the four-quadrant arctangent, available in most programming languages, and hypot is simply sqrt(x*x + y*y), but then computed more carefully (e.g., to avoid overflow etc.), also available in most programing languages.
Is this indeed what you were after?
I'm currently working on making an interface where I have image links that lean towards the mouse cursor. This is more for fun than as a serious project, but nevertheless the information I'm learning from it will be useful in the future. Right now I have several variables setup...
diffx/y = the distance, in pixels, of the cursor from the link's original location. This value goes negative if the cursor goes to the left of or above the link's original location (already calculated).
spacex/y = the amount of distance that I want in between the cursor and the link
calcx/y = the calculated number will be added to the 'style.top' and 'style.left' of the link
calcx = diffx - spacex
calcy = diffy - spacey
link.style.top = calcx
link.style.top = calcy
If I set spacex/y = 0 the link is centered on the cursor
If I set spacex/y = diffx/y the link is set to its normal position
My goal is to have a link that leans slightly towards the cursor (maybe at max 40px from the original position) and
as the cursor gets closer to the link, the link will slowly return to its original position.
When the cursor gets within, let's say, 100px the link should (smoothly) jump towards the cursor as if to say "pick me!"
Here's what the equation would look like as a graph.
I need a way to write this as a javascript equation. I haven't taken algebra in awhile and I'm pretty sure we didn't go over anything that looked like this exactly. I'm guessing it has an exponent and a conditional in there somewhere, but I'm not quite sure. If your able to figure this out, I'd be really thankful (not to mention impressed).
Thank You for your help!
You'll definitely want a piecewise function here (the "conditional" you spoke of). The middle section appears to be an odd-powered polynomial of the form y = Ax^3 or y = Ax^5 for some small value of A (chosen to make y = 150 when x = 150). The curve appears to be essentially linear for |x| >= 200, that is y = x + B for x >= 200 and y = x - B for x <= -200. The transitions between 150 <= |x| <= 200 seem a little trickier, like a shifted exponential or quadratic. But you might start with this (pseudo code):
if (x < -150) {
y = x;
}
else if (x < 150) {
y = (1.0/22500.0) * pow(x, 3);
}
else { // x > 150
y = x;
}
Note that this ignores the transitions between x = 150 and 200 and correspondingly assumes the constants B I mentioned above are zero. But it might get you started.
Edit:
After looking at a plot of my function, I think a 5th order polynomial matches your desired shape more closely. In this case, the middle function will be y = (1.0/506250000.0) * pow(x,5). Results are below. By the way, the constant values are equivalent to 150^-2 for the cubic, and 150^-4 for the quintic function.
I agree it is probably easier to model your function if you split it in parts:
f(x) = x + 50 if x < -200
-150 if -200 <= x < -150
150*(x/150)^k if -150 <= x < 150:
150 if 150 <= x < 200
x - 50 if 200 <= x
for k some big odd number (I'd try 4-10 out...)
You can use one or combination of these:
http://drawlogic.com/2007/09/14/tweener-robert-penner-easing-equation-cheat-sheets/
Or http://www.robertpenner.com/easing/easing_demo.html
I have a rather simple bird's-view 2D game where tower sprites defend against incoming moving sprites by shooting a bullet at them. My question: How do I calculate the needed bullet speed for the bullet to reach its moving target, provided that the bullet will always have the same defined speed?
I'm using JavaScript and have these sprite variables (among others):
sprite.x, sprite.y, sprite.width, sprite.height, sprite.speedX (i.e. velocity), sprite.speedY... so I have the objects originSprite, targetSprite and bulletSprite, all with these type of values, and I need to set the right bulletSprite speed values.
Probably for it to look good, the bullet would start at the outside of the originSprite (or some defined radius, though I guess starting from the originSprite center would also work), but its bullet center would try hit into the center of the targetSprite or so. Note there's no gravity or anything in this world. (Perhaps I should have my sprites variables using angle and velocity but right now I'm using speedX and speedY...)
Thanks so much!
Treat the targets sprite as a straight line in a 2 dimensional room where:
A(time) = (sprite.positionX + sprite.speedX * time, sprite.positionX + sprite.speedX * time)
As your bullet have constant speed you also know:
bullet.speedX^2 + bullet.speedY^2 = bullet.definedSpeed^2
Then you can also calculate a straight line for the bullet:
B(time) = (bullet.positionX + bullet.speedX * time, bullet.positionX + bullet.speedX * time)
And you know that both lines interset somewhere:
A(time) = B(time)
Then it's up to you to solve those equations with your given values and seek a minimum for time.
Some physical insight
1 ) For the target being a "Point Object"
So you have to solve the VECTOR equation
Positionbullet [ time=t1 > t0 ] == Positiontarget [ time=t1 > t0 ] -- (Eq 1)
Where the positions are given by the motion (also VECTOR) equations
Positionobject [ t ] = Positionobject [ t0 ] + Speedobject * ( t - t0 )
Now, the condition for the bullet to be able to reach the target is that the Eq 1 has solutions for x and y. Let's write down the equation for x:
Xbullet [ t0 ] + SpeedXbullet * ( t - t0 ) = Xtarget [ t0 ] + SpeedXtarget * ( t - t0 )
So for the collision time we have
( tCollision - t0 ) = (xtarget [ t 0 ] - xbullet [ t0 ] ) / (SpeedXbullet - SpeedXtarget) -- (Eq 2)
As we need solutions with t > t0, that means that for having an intercept is enough that>
Sign ( xtarget[ t0 ] - xbullet[ t0 ] ) = Sign ( SpeedXbullet - SpeedXtarget ) -- (Eq 3)
Which tells us the evident fact that if an object is moving faster than the other, and in the same direction, they will eventually collide.
From Eq 2, you can see that for a given SpeedXtarget there exist infinite solutions (as already pointed out in other answers) for t and SpeedXbullet, so I think your specifications are not complete.
I guess (as stated in a commentary I made in another answer) thinking in a "tower defense" kind of game, that your bullets have a limited range.
So you need also another constraint:
Distance [ Positiontarget [ tCollision - t0 ] - Positionbullet [ t0 ] ] < BulletRange -- (Eq 4)
Which still permits infinite solutions, but bounded by an upper value for the Collision time, given by the fact that the target may abandon the range.
Further, the distance is given by
Distance[v,u]= +Sqrt[ (Vx-Ux)^2 + (Vx-Vy)^2 ]
So, Eq 4 becomes,
(Xtarget[tCollision - t0] - Xbullet[t0])2 + (Ytarget[tCollision - t0] - Ybullet[t0])2 < BulletRange2 -- (Eq 5)
Note that { Xbullet[t0] , Ybullet[t0} is the tower position.
Now, replacing in Eq 5 the values for the target position:
(Xtarget[t0] + SpeedXtarget * (t-t0) - Xbullet[t0])2 + (Ytarget[t0] + SpeedYtarget * (t-t0) - Ybullet[t0])2 < BulletRange2 -- (Eq 6)
Calling the initial distances:
Dxt0 = Xtarget[t0] - Xbullet[t0]
and
Dyt0 = Ytarget[t0] - Ybullet[t0]
Equation 6 becomes
(Dtx0 + SpeedXtarget * (t-t0) )2 + (Dty0 + SpeedYtarget * (t-t0))2 < BulletRange2 -- (Eq 7)
Which is a quadratic equation to be solved in t-t0. The positive solution will give us the largest time allowed for the collision. Afterwards the target will be out of range.
Now calling
Speedtarget 2 = SpeedXtarget 2 + SpeedYtarget 2
and
H = Dtx0 * SpeedXtarget + Dty0 * SpeedYtarget
TCollision Max = t0 - ( H
+/- Sqrt ( BulletRange2 * Speedtarget 2 - H2 ) ) / Speedtarget 2
So you need to produce the collision BEFORE this time. The sign of the
square root should be taken such as the time is greater than t0
After you select an appropriate flying time for your bullet from the visual
effects point of view, you can calculate the SpeedX and SpeedY for the bullet
from
SpeedXbullet = ( Xtarget [ t0 ] - Xbullet [ t0 ] ) / ( tCollision - t0 ) + SpeedXtarget
and
SpeedYbullet = ( Ytarget [ t0 ] - Ybullet [ t0 ] ) / ( tCollision - t0 ) + SpeedYtarget
2 ) For the target and tower being "Extensive Objects"
Now, it is trivial to generalize for the case of the target being a circle of radius R. What you get, is the equivalent of an "extended range" for the bullets. That extension is just R.
So, replacing BulletRange by (BulletRange + R) you get the new equations for the maximum allowed collision time.
If you also want to consider a radius for the cannons, the same considerations apply, giving a "double extended range
NewBulletRange = BulletRange + RTarget + RTower
Unlimited Range Bullets
In the case that you decide that some special bullets should not have range (and detection) limitations, there is still the screen border constraint. But it is a little more difficult to tackle. Should you need this kind of projectile, leave a comment and I'll try to do some math.
Using vectors can make the math around this seem a little simpler. Sylvester seems to be a promising implementation of vectors in JavaScript, but for the purpose of my example, I'll write my own vector functions. I'm also going to assume .x / .y are measured top/left corner.
// this is a "constant" - representing 10px motion per "time unit"
var bulletSpeed = 10;
// calculate the vector from our center to their center
var enemyVec = vec_sub(targetSprite.getCenter(), originSprite.getCenter());
// measure the "distance" the bullet will travel
var dist = vec_mag(enemyVec);
// adjust for target position based on the amount of "time units" to travel "dist"
// and the targets speed vector
enemyVec = vec_add(enemyVec, vec_mul(targetSprite.getSpeed(), dist/bulletSpeed));
// calculate trajectory of bullet
var bulletTrajectory = vec_mul(vec_normal(enemyVec), bulletSpeed);
// assign values
bulletSprite.speedX = bulletTrajectory.x;
bulletSprite.speedY = bulletTrajectory.y;
// functions used in the above example:
// getCenter and getSpeed return "vectors"
sprite.prototype.getCenter = function() {
return {
x: this.x+(this.width/2),
y: this.y+(this.height/2)
};
};
sprite.prototype.getSpeed = function() {
return {
x: this.speedX,
y: this.speedY
};
};
function vec_mag(vec) { // get the magnitude of the vector
return Math.sqrt( vec.x * vec.x + vec.y * vec.y);
}
function vec_sub(a,b) { // subtract two vectors
return { x: a.x-b.x, y: a.y-b.y };
}
function vec_add(a,b) { // add two vectors
return { x: a.x + b.x, y: a.y + b.y };
}
function vec_mul(a,c) { // multiply a vector by a scalar
return { x: a.x * c, y: a.y * c };
}
function vec_div(a,c) { // divide == multiply by 1/c
return vec_mul(a, 1.0/c);
}
function vec_normal(a) { // normalize vector
return vec_div(a, vec_mag(a));
}
Compute the distance between shooter and target: dist = sqrt((xt - xs)^2 + (yt - ys)^2)
Divide the x and y distances by the above one: nx = (xt - xs)/dist; ny = (yt - ys)/dist; (normalization of the vector)
Multiply the results by a factor to get n pixels per time unit, ie. a speed in each direction. It should give a constant speed in the wanted direction.
I assume that the target will move on a straight line with constant velocity.
If both the direction and the speed of the bullet are variable (i.e. you try to calculation speedX and speedY for the bullet), there are infinitely many solutions.
If you set a fixed direction, you simply intersect the two lines of the bullet and the target. From the distance between the current point of the target and the intersection point (and the target's speed) you can calculate the time the target will take to reach this intersection point.
From the distance between the origin of the bullet and the intersection point (and the previously calculated time) you can calculate the speed of the bullet.