I have a project in which I am using d3js.I have to plot a line.But the twist is the color of line will vary with every array value(every 20px of line holds one element of following array).I have created lines but, I am facing problems with the colour intensity.I thought about for loops,but I am not getting exact results.I think I am not able to swith from one colour to another.
(for example--from dim red-->light red-->little dark red-->dark red)
I have a json with over 10k values.I have simplified my arrays for understanding purpose.
var array_1=[0.0,0.1,0.3,0.5,0.7,0.9]
var array_2=[0.02,0.04,0.06,0.08,0.09]
var array_3=[0.001,0.002,0.004,0.007,0.008]
MyQuestion:For any given color(red,blue,green,yellow etc etc),I should be able to plot the according to these array values in such a way that Greater the number will be,Intense the color will be.
Is it possible to create an algorithm that can manipulate the RGB values of any colour with array values that are numeric?If possible,it will be very kind of you to give some sample.
You just need to convert from YCbCr (YUV) to RGB since
the Y in YUV is luminescence it's as modifying the intensity of the color.
The formulas can be found on wikipedia here:
http://en.wikipedia.org/wiki/YCbCr
There is also an example of this implemented in JavaScript here:
http://www.mikekohn.net/file_formats/yuv_rgb_converter.php
For example on Micael Kohn's page you can try setting a color in RGB
and covert it to YUV. After that just lower or raise the Y value and
convert it to RGB. You will notice that it's like changing the
intensity.
EDIT:
Here you go, wrote an example for you, just click on the div
function yuv2rgb(Y,U,V){
R = Y + 1.4075 * (V - 128)
G = Y - 0.3455 * (U - 128) - (0.7169 * (V - 128))
B = Y + 1.7790 * (U - 128)
return { r:Math.floor(R) , g:Math.floor(G) , b:Math.floor(B)}
}
function rgb2yuv(R,G,B){
Y = R * 0.299000 + G * 0.587000 + B * 0.114000
U = R * -0.168736 + G * -0.331264 + B * 0.500000 + 128
V = R * 0.500000 + G * -0.418688 + B * -.081312 + 128
return { y:Math.floor(Y) , u:Math.floor(U) , v:Math.floor(V)}
}
http://jsfiddle.net/b3FCK/
Related
I reached out for help recently on math.stackexchange.com with a question about 2 dimensional algebra. The answer was promptly provided but it's in mathematical notation unfamiliar to me and the person giving the answer has stopped responding to my questions. While I am extremely grateful to BStar for providing this information, he/she has stopped replying both on the site and the chat, and doesn't seem interested in helping me understand it to the point that I could write programming code to calculate the desired point P. I respect that, but it leaves me stuck for now. Could someone help me convert this sequence of steps into a programming language such as Javascript? (I am actually working in PHP, but Javascript would be more convenient to represent in a runnable Snippet on stackoverflow .. I'm happy with any current language that I can translate into PHP).
The post is at https://math.stackexchange.com/questions/4110517/trig-101-calculate-coords-of-point-p-such-that-it-is-distance-n-from-line-ab-an/4110550?noredirect=1#comment8504010_4110550
The answer given is in Latex but here's a screenshot of it:
The latest description of the process by the author BStar: "Here is the process: First calculate cos B and use arccos to get B. Second calculate tanθ to get θ with arctan by using |BP| is the same from two triangles. Knowing these, we can get vectors BA’ and B’P, thus vectors OA and OP. We get θ to grt vector BA’ in this case, not the other way around. "
I can follow up until step (5) where the comma notation comes in, i.e. k = (-xb, -yb)(xc - xb, yc - yb) / ac. This seems to make k a two dimensional vector but I don't think I ever worked with this notation. Later, k is used in step (6) and (6a) to calculate theta, appearing both in the numerator and denominator of a fraction. I have no idea how to expand this to get an actual value for theta.
(Edit Note: The author BStar assumed point A is at the origin, so (xa, ya) = (0, 0) but I cannot make that assumption in the real world. Thus the vector BA in Step 1 is actually (xa - xb, ya - yb) and his formula for k shown above is actually k = (xa - xb, ya - yb)(xc - xb, yc - yb) / ac. This expansion needs to be carried through the calculation but it's not a major change.)
If we were to frame this in Javascript, I could lay out a framework of what is known at the beginning of the calculation. It's not productive to represent every single step of the mathematical proof given by BStar, but I'm not sure exactly what steps can be left as processes in the mathematical proof and what steps need expounding in code.
/* Known points - A, B, C */
var xa = 10, ya = 10;
var xb = 100, yb = 500;
var xc = 700, yc = 400;
/* Known lengths m and n (distance perpendicularly from AB and AC) */
var m = 30;
var n = 50;
/* Point we want to calculate, P */
var px = 0, py = 0;
/* Calculation goes here - some Javascript notes:
* var a = Math.sin(angInRadians);
* var b = Math.asin(opposite / hypotenuse);
* var c = Math.pow(number, 2); // square a number
* var d = Math.sqrt(number);
*/
/* Print the result */
console.log('Result: P (' + px + ', ' + py + ')');
How would one express the maths from the diagram in the programming snippet above?
I think I can get you to the angle of B but I'm not very good with math and get lost with all those variables. If you are stuck at figuring out the angle try this and see if it does what you want. It seems to do what step 5 is asking but double check my work.
let pointA = {x: 100, y: 0};
let pointB = {x: 20, y: 20};
let pointC = {x: 0, y: 100};
let distBA_x = pointB.x - pointA.x;
let distBA_y = pointB.y - pointA.y;
//let BA_a = Math.sqrt(distBA_x*distBA_x + distBA_y*distBA_y);
let distBC_x = pointB.x - pointC.x;
let distBC_y = pointB.y - pointC.y;
//let BC_c = Math.sqrt(distBC_x*distBC_x + distBC_y*distBC_y);
var angle = Math.atan2(distBA_x * distBC_y - distBA_y * distBC_x, distBA_x * distBC_x + distBA_y * distBC_y);
if(angle < 0) {angle = angle * -1;}
var degree_angle = angle * (180 / Math.PI);
console.log(degree_angle)
I've laid it out on a canvas so you can see it visually and change the parameters. Hope it helps. Here's the Codepen https://codepen.io/jfirestorm44/pen/RwKdpRw
BA • BC is a "dot product" between two vectors. The result is a single number: It's the sum of the products of vector components. If the vectors are (x1,y1) and (x2,y2) the dot product is x1x2+y1y2.
Assuming you don't have a library for vector calculations and don't want to create one, the code for computing k would be:
k = (-xb*(xc - xb)-yb*(yc - yb)) / ac
This is a continuation from my previous posts on the bubble chart I have been struggling to make. I have achieved my desired effect by adapting Chris Tufts's code:
https://blockbuilder.org/lydiawawa/347e2b0aeed51d7dc56fde40b08e5fcd
However, when I attempt to add tooltip, I'm unable to extract the original value of BMI and Race(In the code, BMI = size and Race = group) This is because .data is calling nodes instead of the original data. Does anyone know how to point the tooltip to grab the right values?
I know that I should define group and size in create_node function such as the following, but I received an unexpected var token error.
function create_nodes(data,node_counter) {
var i = cs.indexOf(data[node_counter].group),
var z = cs.data[node_counter].group,
var s = cs.data[node_counter].size,
r = Math.sqrt((i + 1) / m * -Math.log(Math.random())) * maxRadius,
d = {
cluster: i,
z,
s,
radius: radiusScale(data[node_counter].size)*1.5,
text: data[node_counter].text,
x: Math.cos(i / m * 2 * Math.PI) * 200 + width / 2 + Math.random(),
y: Math.sin(i / m * 2 * Math.PI) * 200 + height / 2 + Math.random()
}
if (!clusters[i] || (r > clusters[i].radius)) clusters[i] = d;
console.log(d);
return d;
};
You can easily create the size property the same way you created the group one:
size: data[node_counter].size,
By the way, you have a syntax error (you're missing the colon) in the group one, which should be:
group: data[node_counter].group,
Here is your updated bl.ocks: https://bl.ocks.org/GerardoFurtado/5802f23a0bd1c4a3f94f95eded56bc97/dc36321d0d4bb7db2a44246f9330f22099276524
PS: as a friendly advice, you don't need that cumbersome function. Just change the data array and pass it directly to the layout.
I am trying to write a function that calculates the soft light given a foreground and a background color.
The function is below;
var background = '0xFFFFFF';
var foreground = '0x47768C';
var calculateSoftlight = function (background, foreground) {
var intBackground = parseInt(background, 16);
var intForeground = parseInt(foreground, 16);
var softlight = (1 - (2 * intForeground)) * (intBackground*intBackground) + (2 * intForeground * intBackground);
return softlight.toString(16);
}
calculateSoftlight(background, foreground); //-8eed155338bb200000
I am using the Pegtop formula as listed here; http://en.wikipedia.org/wiki/Blend_modes. I am unsure of the correct implementation of this. Any ideas?
Apply the formula to each RGB value instead of using Hex. If you need to use Hex as an input you'll probably need to convert.
You will need to normalize each value (so value / 255) and use that in the formula. Then multiply (and round) the result by 255 to convert back to 8-bit value.
Something like this should be close, I haven't used that formula specifically though so this is untested.
var top = top / 255,
bot = bot / 255;
top = ((1 - 2*bot)*Math.pow(top, 2)) + 2*bot*top,
top = Math.round(top * 255);
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Did you ever played the "Tank wars" game?
I'm programming this game with JavaScript + Canvas (for a personal challenge), and what I need is an algorithm for generating that random green land every time I start the game, but I'm not too good at maths, so I can't do it myself.
I don't want someone to give me the code, I only want the idea for the algorithm.
Thanks!
(9 segments)
Fiddle demo
(7 segments)
The main generation function look like this:
var numOfSegments = 9; // split horizontal space
var segment = canvas.width / numOfSegments; // calc width of each segment
var points = [], calcedPoints;
var variations = 0.22; // adjust this: lower = less variations
var i;
//produce some random heights across the canvas
for(i=0; i < numOfSegments + 1; i++) {
points.push(segment * i);
points.push(canvas.height / 2.8 + canvas.height * variations * Math.random());
}
//render the landscape
ctx.beginPath();
ctx.moveTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
calcedPoints = ctx.curve(points); // see below
ctx.closePath();
ctx.fillStyle = 'green';
ctx.fill();
The curve() function is a separate function which generate a cardinal spline. In here you can modify it to also store tension values to make more spikes. You can also used the generated points as a basis for where and at what angle the tanks will move at.
The function for cardinal spline:
CanvasRenderingContext2D.prototype.curve = function(pts, tension, numOfSegments) {
tension = (tension != 'undefined') ? tension : 0.5;
numOfSegments = numOfSegments ? numOfSegments : 16;
var _pts = [], res = [], t, i, l, r = 0,
x, y, t1x, t2x, t1y, t2y,
c1, c2, c3, c4, st, st2, st3, st23, st32;
_pts = pts.concat();
_pts.unshift(pts[1]);
_pts.unshift(pts[0]);
_pts.push(pts[pts.length - 2]);
_pts.push(pts[pts.length - 1]);
l = (_pts.length - 4);
for (i = 2; i < l; i+=2) {
//overrides and modifies tension for each segment.
tension = 1 * Math.random() - 0.3;
for (t = 0; t <= numOfSegments; t++) {
t1x = (_pts[i+2] - _pts[i-2]) * tension;
t2x = (_pts[i+4] - _pts[i]) * tension;
t1y = (_pts[i+3] - _pts[i-1]) * tension;
t2y = (_pts[i+5] - _pts[i+1]) * tension;
st = t / numOfSegments;
st2 = st * st;
st3 = st2 * st;
st23 = st3 * 2;
st32 = st2 * 3;
c1 = st23 - st32 + 1;
c2 = -(st23) + st32;
c3 = st3 - 2 * st2 + st;
c4 = st3 - st2;
x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x;
y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y;
res[r++] = x;
res[r++] = y;
} //for t
} //for i
l = res.length;
for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]);
return res; //return calculated points
}
Look into perlin noise generation, this in combination with a good smoothing algorithm can produce some pretty good terrain, and is fairly quick. There is a reference version of the code kicking around the net somewhere, which should provide you with a fairly hefty headstart
First you need a point that is random y (between 55,65); got x=0
So this is the origin point for the green, lets keep it as x1,y1 (x1 always 0).
Then you need a random integer between 30 to 40. This is x2. And a random y which is in the range y1 + 8 to y1 + 20.
Then x3 and y3 on same principle (lets call it formula type 1)
Now you need to first get a random either -1 or 1, this will be directions of y4. So y4 can go higher than y3 or lower ... this will be formula type 2.
You need to keep a max and min y for a new y, if it crosses that then go the other way -> this will be a correction type formula 3.
Xn keeps increasing till its >= width of board.
Join the lines in a eclipses ... and looks like web searches is the way to go !
I am sure there are a lot of coded libraries that you could use to make this easy. But if you are trying to code this by yourself, here is my idea.
You need to define terrain from everything else. So every part of your environment is a cluster for example. You need to define how are separated these clusters, by nodes(points) for example.
You can create a polygon from a sequence of points, and this polygon can become whatever you want, in this case terrain.
See that on the image you passed, there are peaks, those are the nodes (points). Remember to define also nodes on the borders of your environment.
There are surely a novel, written algorithms, either fractal as #DesertIvy pointed out or others, maybe there are libraries as well, but if you want toi generate what is in the image, it can be pretty straightforward, since it is just (slightly curved) lines between points. If you do it in phases, not trying to be correct at once, it is easy:
Split x region of your game screen into sections (with some minimal and maximal width) using random (you may be slightly off in last section, but it does not matter as much, I think). Remember the x-es where sections meet (including the ones at game screen border)
Prepare some data structure to include y-s as well, on previously remembered x-s. Start with leftmost.y = 0, slope = Math.random()-0.5;.
Generate each next undefined y beginning with 1: right.y = left.y + slope * (right.x-left.x); as well as update slope after each y: slope += Math.random()-0.5;. Do not bother, for the moment, if it all fits into game screen.
If you want arcs, you can generate "curviness" parameter for each section randomly which represent how much the middle of the line is bumped compared to straight lines.
Fit the ys into the game screen: first find maximal and minimal generated y (mingeny, maxgeny) (you can track this while generating in point 4). Choose where the max and min y in game screen (minscry, maxscry) (say at the top fourth and at the bottom fourth). Then transform generated ys so that it spans between minscry and maxscry: for every point, do apoint.y = minscry + (maxscry-minscry)/(maxgeny-mingeny)*(apoint.y-mingeny).
Now use lines between [x,y] points as a terrain, if you want to use "curviness", than add curvemodifier to y for any particular x in a section between leftx and rightx. The arc need not to be a circle: I would suggest a parabola or cosine which are easy to produce: var middle = (left.x+right.x)/2; var excess = (x-left)/(middle-left); and then either var curvemodifier = curviness * (1-excess*excess); or var curvemodifier = curviness * Math.cos(Math.PI/2*excess).
Wow...At one point I was totally addicted to tank wars.
Since you are on a learning adventure...
You might also learn about the context.globalCompositeOperation.
This canvas operation will let you grab an image of actual grass and composite it into your game.
You can randomize the grass appearance by changing the x/y of your drawImage();
Yes, the actual grass would probably be too distracting to include in your finished game, but learning about compositing would be valuable knowledge to have.
...and +1 for the question: Good for you in challenging yourself !
I'm trying to find the row, column in a 2d isometric grid of a screen space point (x, y)
Now I pretty much know what I need to do which is find the length of the vectors in red in the pictures above and then compare it to the length of the vector that represent the bounds of the grid (which is represented by the black vectors)
Now I asked for help over at mathematics stack exchange to get the equation for figuring out what the parallel vectors are of a point x,y compared to the black boundary vectors. Link here Length of Perpendicular/Parallel Vectors
but im having trouble converting this to a function
Ideally i need enough of a function to get the length of both red vectors from three sets of points, the x,y of the end of the 2 black vectors and the point at the end of the red vectors.
Any language is fine but ideally javascript
What you need is a base transformation:
Suppose the coordinates of the first black vector are (x1, x2) and the coordinates of the second vector are (y1, y2).
Therefore, finding the red vectors that get at a point (z1, z2) is equivalent to solving the following linear system:
x1*r1 + y1*r2 = z1
x2*r1 + y2*r2 = z2
or in matrix form:
A x = b
/x1 y1\ |r1| = |z1|
\x2 y2/ |r2| |z2|
x = inverse(A)*b
For example, lets have the black vector be (2, 1) and (2, -1). The corresponding matrix A will be
2 2
1 -1
and its inverse will be
1/4 1/2
1/4 -1/2
So a point (x, y) in the original coordinates will be able to be represened in the alternate base, bia the following formula:
(x, y) = (1/4 * x + 1/2 * y)*(2,1) + (1/4 * x -1/2 * y)*(2, -1)
What exactly is the point of doing it like this? Any isometric grid you display usually contains cells of equal size, so you can skip all the vector math and simply do something like:
var xStep = 50,
yStep = 30, // roughly matches your image
pointX = 2*xStep,
pointY = 0;
Basically the points on any isometric grid fall onto the intersections of a non-isometric grid. Isometric grid controller:
screenPositionToIsoXY : function(o, w, h){
var sX = ((((o.x - this.canvas.xPosition) - this.screenOffsetX) / this.unitWidth ) * 2) >> 0,
sY = ((((o.y - this.canvas.yPosition) - this.screenOffsetY) / this.unitHeight) * 2) >> 0,
isoX = ((sX + sY - this.cols) / 2) >> 0,
isoY = (((-1 + this.cols) - (sX - sY)) / 2) >> 0;
// isoX = ((sX + sY) / isoGrid.width) - 1
// isoY = ((-2 + isoGrid.width) - sX - sY) / 2
return $.extend(o, {
isoX : Math.constrain(isoX, 0, this.cols - (w||0)),
isoY : Math.constrain(isoY, 0, this.rows - (h||0))
});
},
// ...
isoToUnitGrid : function(isoX, isoY){
var offset = this.grid.offset(),
isoX = $.uD(isoX) ? this.isoX : isoX,
isoY = $.uD(isoY) ? this.isoY : isoY;
return {
x : (offset.x + (this.grid.unitWidth / 2) * (this.grid.rows - this.isoWidth + isoX - isoY)) >> 0,
y : (offset.y + (this.grid.unitHeight / 2) * (isoX + isoY)) >> 0
};
},
Okay so with the help of other answers (sorry guys neither quite provided the answer i was after)
I present my function for finding the grid position on an iso 2d grid using a world x,y coordinate where the world x,y is an offset screen space coord.
WorldPosToGridPos: function(iPosX, iPosY){
var d = (this.mcBoundaryVectors.upper.x * this.mcBoundaryVectors.lower.y) - (this.mcBoundaryVectors.upper.y * this.mcBoundaryVectors.lower.x);
var a = ((iPosX * this.mcBoundaryVectors.lower.y) - (this.mcBoundaryVectors.lower.x * iPosY)) / d;
var b = ((this.mcBoundaryVectors.upper.x * iPosY) - (iPosX * this.mcBoundaryVectors.upper.y)) / d;
var cParaUpperVec = new Vector2(a * this.mcBoundaryVectors.upper.x, a * this.mcBoundaryVectors.upper.y);
var cParaLowerVec = new Vector2(b * this.mcBoundaryVectors.lower.x, b * this.mcBoundaryVectors.lower.y);
var iGridWidth = 40;
var iGridHeight = 40;
var iGridX = Math.floor((cParaLowerVec.length() / this.mcBoundaryVectors.lower.length()) * iGridWidth);
var iGridY = Math.floor((cParaUpperVec.length() / this.mcBoundaryVectors.upper.length()) * iGridHeight);
return {gridX: iGridX, gridY: iGridY};
},
The first line is best done once in an init function or similar to save doing the same calculation over and over, I just included it for completeness.
The mcBoundaryVectors are two vectors defining the outer limits of the x and y axis of the isometric grid (The black vectors shown in the picture above).
Hope this helps anyone else in the future