Gradient a Parallelogram - javascript

I'm working in JavaScript drawing on a canvas, and have four coordinates to draw a parallelogram, called A, B, C, and D starting from the top-left, top-right, bottom-left, and bottom right, respectively.
An example of some coordinates might be:
A: (3, 3)
B: (4, 3)
C: (1, 0)
D: (2, 0)
I can draw the parallelogram just fine, but I would like to fill it in with a gradient. I want the gradient to fill in from left to right, but matching the angle of the shape. The library I use (CAKE) requires a start and stop coordinate for the gradient. My stop and start would be somewhere half way between A and C, and end somewhere half way between B and D. Of course, it is not simply EXACTLY half way because the angles at A, B, C, and D are not right angles. So given this information (the coordinates), how to I find the point on the line A -> C to start, and the point on the line B -> D to stop?
Remember, I'm doing this in JavaScript, so I have some good Math tools at my disposal for calculation.

What you specified in your comment is doable with more information (e.g. you need to specify where the perpendicular line starts as that will affect your gradient a lot), but I don't think it will get you what you want.
Instead, take the following for example, which I think is closer to what you are striving for:
As you can see, to make the gradient for the above parallelogram we ignore the AC and BD sides and make the gradient relative to AB and CD. You can decide which pair of sides to use, but I would probably go by length so that the display is consistent across all your parallelograms (either you want the gradient relative to the pair of longer sides or the shorter ones, your choice, but personally I'd go with the longer sides).
Let's say you pick AB. The slope of the line perpendicular to AB is the inverse reciprocal of the slope of AB, which is (ax-bx)/(by-ay) (careful about the dividing by zero case here!).
Next, you have to find 2 gradient points, which will be two appropriate points on any line with that slope. One option is to pick the line going through A, use A as the starting point, and use the point where it intersects with CD as the ending point (you can use this page as a guide for figuring out the intersection point). Otherwise, keep the slope but tweak the points to your liking to get the gradient you want.
Once you have your points for your gradient, plug them in and it's a piece of CAKE!

Related

Geometry on Latitude/Longitude (Projection of point on arc)

I just want to check if there is a point (lat, long) of the projection intersecting with the arc giving by 2 points (lat, long) and if it does, I want to find that (lat, long).
Can (lat, long) be used as a 2D vector space to make this problem similar to the one in cartesian co-ordinates? How accurate would it be?
While the answer on Link helps with getting the distance to the arc, how can I know whether the point of intersection is between the points that were used to find the great circle? Also would it be possible to solve this without having to use switch to cartesian co-ordinates?
There are two ways to approach this.
The first assumes a straight line between the two points--although, in actuality, such a line would intersect with the earth.
The second actually determines the great-circle route between the two points, that is, the minimum-length arc that actually follows the earth's surface and joins the two points. To do this, you have to use coordinate transformations to generate vectors of direction cosines for the two superficial points. Call them A and B.
To determine whether C lies on that arc, you can't just do linear interpolation like you could if you cheated and used a line segment that passes through the earth. Instead, you need to calculate the direction cosines for C also. C lies true between A and B if angles AC, BC, and AB are all equal. Angles can be determined by calculating the dot products of the corresponding direction cosines and evaluating the inverse cosine thereof.

2d perspective skew in JS

I want to transform an image in 2 points perspective.
I guess I need to transfer to JS a formula from: http://web.iitd.ac.in/~hegde/cad/lecture/L9_persproj.pdf
But I'm humanities-minded person and I faint when I see matrices.
Here's what I need exactly:
I have a two vanishing points: X(X.x, X.y) and Z(Z.x, Z.y). And rectangle ABCD (A.x, A.y and so on)
(source: take.ms)
And I want to find new nA, nB, nC and nD points with which I can transform my rectangle like that (the points order doesn't really matter):
(source: take.ms)
Right now I'm doing weird approximate calculations: I'm looking for most distant point from X (1), then lay over an interval towards Z (2), than another interval towards X (3) and then again from Z (4):
(source: take.ms)
The result is a bit off but is alright for the precision I need, but this algorithm sometimes gives very weird results if I change vanishing points, so if there's a proper solution I'll gladly use it. Thanks!

Tile Filling Algorithm for Game

Background:
I am working on a tile-based game in Javascript where a character freely moves around the map (no diagonal - Left/Right/Up/Down) and fills in tiles as he moves around the map. There are three tile types -- tiles you've filled (blue), your current path (red), and empty ones (black). There are also enemies (stars) that move around the map as well, but only in empty areas. The objective is to fill as much of the map as possible.
Map is sized as roughly 40x40 tiles. There is a 1 tile thick border around the entire outside of the map that is already "filled" (blue).
I have established that a flood-fill algorithm will work for filling up areas of tiles when needed. However, my problem is as follows:
PROBLEM STATEMENT:
I want to only fill a sectioned-off part of the map if there are no enemies in it.
My Question:
I could run flood-fill algorithm and stop it if it reaches a tile occupied by an enemy -- however, is this the most efficient approach (for a real time game)?
IF YES, how do I determine where to start the algorithm from in a systematic way since there are multiple areas to check and the character doesn't have to move in a perfectly straight line (can zig-zag up/down/right/left, but can't move diagonally).
Picture Example 1 (pics explain better):
Note: red areas turn blue (filled) once you reach another filled area. In example below, there are no enemies in the contained area, so the area is filled.
Picture Example 2:
In this second example, there is an enemy within the contained area (and on the outside area - not shown) so nothing but the line is filled.
Summary: What is the best approach for doing this type of filling? Is flood fill the best choice for determining whether to fill or not -- 40x40 makes for a pretty large calculation. If yes, how do I determine what tile do I start with?
Let me suggest a different way of looking at your problem.
Going by the description of your game, it seems like the user's main, perhaps only, "verb" (in game design terms) is to draw a line that divides the open area of the field into two sections. If either of these two sections is free of enemies, that section gets filled in; if neither section is free of enemies, the line remains but both sections remain open. There are no other conditions determining whether a section gets filled or not, right?
So the most efficient way to solve this problem, I would think, is simply to draw a continuous line, which may make corners but only moves in horizontal or vertical directions, from one of your enemies to every other enemy in turn. We'll call this line the "probe line". From here on, we're using the approach of Derek's suggested "Ray casting algorithm": We look at the number of times the "probe line" crosses the "border line", and if the number of crossings is ever odd, it means you have at least one enemy on each side of the line, and there's no filling.
Note, though, that there's a difference between the two lines coinciding and the two lines crossing. Picture a probe line that goes from the coordinates (0,10) to (39,10) , and a border line that goes down from (5,0) to (5,10) and then goes right to (13,10). If it goes down from there towards (13,39), the two lines are crossing; if instead it goes upwards toward (13,0), they're not.
After a lot of thought, I strongly suggest that you store the "border line", and construct the "probe line", in terms of line segments - rather than trying to determine from which cells are filled which line segments created them. That will make it much harder than it has to be.
Finally, one odd game design note to be aware of: unless you constrict the user's control so that he cannot bring the border line back to within one cell of itself, then a single border line drawn by a user might end up sectioning off the field into more than two sections - there could be sections created by the border line looping right back on itself. If you allow that, it could very drastically complicate the calculation of where to fill. Check the following diagram I made via Derek's fiddle (thank you, Derek!):
As you can see, one border line has actually created three sections: one on the upper side of the line, one below the line, and one formed by the line itself. I'm still thinking about how that would affect things algorithmically, for that to be possible.
EDIT: With a) time to think about the above creation-of-multiple-sections-by-loops, and b) the Simulation of Simplicity resource brought up by Derek, I think I can outline the simplest and most efficient algorithm that you're likely to get.
There's one subproblem to it which I'll leave to you, and that is determining what your new sections are after the player's actions have drawn a new line. I leave that to you because it's one that would have had to be solved before a solution to your original problem (how to tell if there are enemies within those sections) could have been called.
The solution, presented here as pseudocode, assumes you have the border of each section stored as line segments between coordinates.
Create a list of the sections.
Create a list of the enemies.
Continue as long as neither list is empty:
For each enemy in the enemy list:
Designate "Point A" as the coordinates of the enemy, PLUS 0.5 to both x and y.
For each section in the section list:
Designate "Point B" as the upper-left-most coordinate, PLUS 0.5 to both x and y.
Count how many of the section border segments cross a line between A and B.
If the answer is even:
remove this section from the section list
skip forward to the next enemy
If any sections remain in the list, they are free of enemies. Fill them in.
The addition of the 0.5 to the coordinates of the "probe line" are thanks to Derek's SoS resource; they eliminate the difficult case where the lines coincide rather than simply crossing or not crossing.
If you have the points of the border of your shape that lies on the same y as the enemy, then you can simply count the number of borders, starting from either left or right to the enemy. If it's odd then it's inside. If it's even then it's outside.
Since you are using a grid system this should be easy to implement (and very fast). This algorithm is called the Ray casting algorithm.
Here's a simple example I created: http://jsfiddle.net/DerekL/8QBz6/ (can't deal with degenerate cases)
function testInside(){
var passedBorder = 0,
passingBorder = false;
for(var x = 0; x <= enemy[0]; x++){
if(board[x][enemy[1]] === 1) passingBorder = true;
else if(board[x][enemy[1]] === 0 && passingBorder){
passingBorder = false;
passedBorder++;
}
}
return !!(passedBorder%2);
}
For example, you have this shape which you have determined:
removed
Guess what I found, (slightly modified)
//simple enough, it only needs the x,y of your testing point and the wall.
//no direction or anything else
function testInside3() {
var i, j, c = 0;
for (i = 0, j = wallList.length-1; i < wallList.length; j = i++) {
if ( ((wallList[i][1]>enemy[1]) ^ (wallList[j][1]>enemy[1])) &&
(enemy[0] < (wallList[j][0]-wallList[i][0]) * (enemy[1]-wallList[i][1]) / (wallList[j][1]-wallList[i][1]) + wallList[i][0]) )
c = !c;
}
return !!c;
}
http://jsfiddle.net/DerekL/NvLcK/
This is using the same ray casting algorithm I mentioned, but this time the "ray" is now mathematical using the following inequality for x and a condition for y:
(X2 - X1)(Py - Y1)
Px < ────────────────── + X1
Y2 - Y1
which is derived by combining these two:
Ray:
x(t) = Px + t, y(t) = Py, where t > 0 (the ray goes to the right)
Edge:
x(u) = (X2 - X1)u + X1, y(u) = (Y2 - Y1)u + Y1, where 0 <= u <= 1
And the condition for y:
(Y1 > Py) ⊕ (Y2 > Py)
which is equivalent to:
(Y1 ≥ Py > Y2) ∨ (Y2 ≥ Py > Y1)
and yadi yadi yada some other interesting technical stuff.
Seems like this is the default algorithm in many native libraries. The method used to dealing with degenerate cases is called Simulation of Simplicity, described in this paper (section 5.1).
Nevertheless, here's the result generated with the algorithm testing every coordinate:
If it's easy to determine where the borders of a region to possibly fill are, you can use the following approach:
Assign each edge a clockwise directionality. That is, construct a vector for each edge that starts on its corners and has a direction such that a clockwise path around the region is described by these vectors.
For each enemy:
Construct a vector starting from the enemy and ending on the closest edge. We'll call this an enemy_vector.
Calculate the cross product of the enemy_vector and the vector corresponding to the closest edge. The sign of the cross product will tell you whether the enemy is inside the region: if it's positive, the enemy is outside of it, and if it's negative it isn't!
EXAMPLE:
Suppose we have the following region and enemy to evaluate the inside-ness of.
We can encode the region as a series of vectors that give it a clockwise orientation, like so:
So how do we use that to determine the side of the region inhabited by the enemy? We draw a vector from it (which I've colored red) to the nearest edge (which I've colored green)...
...and take the cross product of the red vector and the green vector. Application of the right-hand rule tells us that (red) x (green) > 0, so the enemy must be outside the region!

Interconnected curved lines

Given a series of JSON co-ordinates typically in the format:
{from: {x:0, y:0}, to: {x:0, y:10}, ...}
I would like to draw a series of straight dotted paths which are connected with simple, fixed radius rounded corners. I have been looking at Slope Intercept Form to calculate the points along the straight line but I am a little perplexed as to the approach for calcualting the points along the (Bezier?) curves.
e.g. I want to draw curves between p1 and p2 and p3 and p4. Despite what the poor mockup might imply I am happy for the corners to be a fixed radius e.g. 10px
I would like to abstract out the drawing logic and therefore am seeking a generalised approach to returning a JavaScript point array which I can then render in a number of ways (hence I am avoiding using any inbuilt functions provided by SVG, Canvas etc).
What you want is a cubic bezier curve.
http://www.blackpawn.com/texts/splines/
Look at the first applet on this page. If A is p1, D is p2, the direction A-B is line 1's angle and the direction C-D is line 2's angle you can see how this gives you the properties you need - it starts at angle 1 and ends at angle 2 and is flush with the points.
So, to get your points C and D, one way to do this would be to take the line segment 1, copy it, place it starting at p1 - and say where the new line ends is B, and similar with line segment 2 and p2 for D. (And you could do things like have a factor that multiplies into the copied line segments' distance to make the curves stick out more or less... etc)
Then just do the math :)
http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
And once you have your equation for the curve, step through it with a delta t of the desired precision (e.g. every 0.1 of t, every 0.01...) and spit out every pair of points on the curve as a line segment.

Javascript method to find intersection point of two lines given three points and slopes

I searched for this and found similar answers but they were more math based than programming based, and I need a little help putting it in to code.
I have an arbitrary shape, but let's call it a diamond for now, with the following coordinates:
A = (0,0)
B = (50, 50)
C = (0, 100)
D = (-50, 50)
Think of the movement contraints on this as if you had a rubber band and moved a peg. The lines will always connect but their orientation to one another must not change. So since the slope of AB is 1, it needs to remain 1. I have that part working fine.
Now, say I move "B" such that it rests at (100, 100). I know the slopes of AB (unchanged), BC (before B was moved, and after, but after is useless and wrong), CD (unchanged) and DA (unchanged). I also know the coordinates of A, B and D. I need to find the position of C, such that all slopes remain unchanged and it rests at the logical point where BC and CD should intersect.
Mathematically, I know C belongs at (50, 150) now but I need a generalized formula to figure this out. This is a single example so what I'm looking for is something generalized enough to reuse. Of course, there are snags when lines are parallel or vertical but I can handle that.
This picture should help visualize it. B started at "B" and I moved it to "B2". C needs to move to ???
Thanks a ton if you can help!
EDIT: This seems to be the answer, but I'm anything but a math whiz and don't get how it translates in to some sort of generalized formula. How do you detect where two line segments intersect?

Categories