Random point outside of a set bounds? - actionscript-3

I want to generate a point (x,y) that is outside of my screen. The reason for this is I want to tween an object towards the outside of the screen, and the reason for tweening rather than just giving it a random X and Y velocity is because for this instance tweening using greensock is simpler than creating an update loop.
So, what is an elegant way to generate that number? My current solution is crude and doesn't allow for things to tween towards corners.
var quad:int = irand(1, 4); //generates a random integer between and including the min and max
var maxX:Number = frame.width;
var minX:Number = -frame.width;
var maxY:Number = frame.height;
var minY:Number = -frame.height;
if (quad == 1) //top
{
maxY = -frame.height;
minY = -frame.height - 50;
}
else if (quad == 2) //left
{
maxX = -frame.width;
minX = -frame.width - 50;
}
else if (quad == 3) //bottom
{
maxY = frame.height + 50;
minY = frame.height;
}
else if (quad == 4) //right
{
maxX =frame.width + 50;
minX = frame.width;
}
//first param is duration in seconds
//rand generates a number between the given values
objectToTween.tweenTo(rand(1,2), {
x: rand(minX, maxX),
y: rand(minY, maxY),
repeat: -1,
yoyo: false,
scaleX: 1,
scaleY: 1,
delay: rand(0,1),
ease: Quad.easeIn});
So hopefully it's clear that this solution picks a random direction and tweens the object towards that direction. I'm wondering if there is a way to generate a random number between two given ranges. (such as, between -100 and 100, but excluding -50 through 50) and then applying that for 2 dimensions

what you want
So you have a rectangular frame f:
┌───┐
│ │
│ f │
│ │
└───┘
and a rectangular bounding box of an object o to be tweened to the outside of f:
┌─────┐
│ o │
└─────┘
the outside of f is a position of o in which both f and o touch each other but do not overlap.
Some such valid target positions of o are shown below:
┌───┐
│ │
│ f ├─────┐ 1
│ │ o │
└───┴─────┘
┌───┐
│ │
│ f │
│ │ 2
┌───┴─┬─┘
│ o │
└─────┘
┌─────┐
│ o ├───┐
└─────┤ │ 3
│ f │
│ │
└───┘
┌─────┐
│ o │
└┬───┬┘
│ │ 4
│ f │
│ │
└───┘
Due to the contact of o and f, one side of o is always shared with f. For the above cases, that is
f's right is o's left
f's bottom is o's top
f's left is o's right
f's top is o's bottom
In the edge cases (pun intended), two edges are shared, that is, there is one corner point shared (from example 3, shifting o up a little):
┌─────┐
│ o │
└─────┼───┐
│ │
│ f │
│ │
└───┘
o cannot go any further up or to the left. Keep in mind the definition of the outside of f that I stated above which is perfectly adequate and a lot simpler than "the infinity of space excluding the rectangle f".
If you shift o over to the right, you get the maximum of the x position (the right most position):
┌─────┐
│ o │
┌───┼─────┘
│ │
│ f │
│ │
└───┘
I hope this illustrates that at least one dimension is always predetermined by what sides are touching each other and the other is chosen at random from within the limits. At those limits (minimum and maximum) the two frames will only touch each other at the corners.
There's your problem:
x: rand(minX, maxX),
y: rand(minY, maxY),
instead, first set 1 dimension of o randomly to one of the cases represented in the 4 examples above. Either
x is determined by either f's left or
right (also depending on width and registration point of o), or
y is determined by either f's top or bottom (also depending on heihgt and registration point of o)
the other one is chosen at random from with in the limits.
what you need
There's so much randomisation going on that it is hardly justifiable to put that much effort into determining a target position.
Consider an alternative approach. Determine a circle around f, that will guarantee to be outside of f. Then randomly determine an angle (direction) and tween according to that. This will make the tweens appear slightly different, because the duration they are visible varies depending on the direction (angle), but this difference will be barely noticeable.

Related

Octave select part of image

I have a 2-D 512x512 image and I want to display the middle section i.e. A(256-50:256+50,256-50:256+50) but cannot get to work using imshow.
You can use imcrop function
pkg load image
x = 256-50; // starting position (x cordinate)
y = 256-50; // starting position (y cordinate)
a = 100;
b = 100;
B = imcrop(A, [x y a b]);
imshow(B);
This will crop the image starting from x,y by 100 pixels

CanvasPixelArray - how many index spots for one color value?

For a personal project, I'm re-implementing some Javascript code to Java. One particular thing that is tripping me up at this point is whether a Color is represented by three or four index values in the HTML5 CanvasPixelArray object.
The page linked above states that an offset value of 4 is used. However, one graphic effect that I'm re-implementing has this function:
function getPixelValue(x, y) {
var offset = (x + y * width) * 4;
var r = imageData[offset];
var g = imageData[offset + 1];
var b = imageData[offset + 2];
return ( ((255 << 8) | r) << 8 | g) << 8 | b;
}
to return an color integer value for a given pixel. The code works in the browser, but I'm confused by the fact that r, g, b are all contained in a given 3 block segment of the array, while offset is 4. This same value for offset is shown in the code example at the page linked above.
What is the reason for the difference? If a pixel color value is contained within a 3 block segment, shouldn't offset include 3 as a constant?
Canvas always returns RGBA but you can skip the alpha channel (index 3) if you don't need it but will always have to skip 4 positions in the byte array.
Typically for photos the alpha value is always 255 (non-transparent) so it isn't needed. For other types of graphics which already contain an alpha channel (for example PNG icons etc.) the alpha channel becomes more important.
Your getPixelValue simply ignores the alpha channel and returns the RGB value independent on the value of the alpha channel (which is correct when you want a color value from the source - the color value (from source) will be the same regardless of the alpha value).

Overlapping line segments in 2D space

I need to find whether two lines overlap each other. I have the intersection code which returns 0, if two lines are parallel. But then I need to know if these two parallel lines overlap.
Edit:
A C B D
-----------------------------------------------
Line 1: A-B
Line 2: C-D
I need to find if Line 1 overlaps Line 2, but both lines can have a slope > 0.
You can compare to find if there is no over lap. you will have less comparisons in this way thus very efficient. Do following comparisons
D < A
B < C
If either case is true the lines are not overlapping. otherwise there must an overlap.
You will make least number of comparisons to determine if they are not overlapping. Otherwise there will be more comparisons to make.
Since you know they're both parallel, then just check whether line segment CD contains either of the endpoints of the first line (point A and point B).
For two co-linear line segments that are not necessarily axis-aligned:
Sort the vertices in clockwise order around the origin.
The lines overlap if the ordered vertices alternate between the two segments, e.g. Line1.Point1, Line2.Point1, Line1.Point2, Line2.Point2.
It is sufficient to calculate the areas of triangles ACB and CBD. If the area is 0, then the points are collinear, and if both areas are zero then the lines are overlapping.
You can calculate the area of a triangle ABC by this formula:
2*Area(ABC)= (bx – ax)(cy – ay) – (cx – ax)(by – ay);
Line equation is direction of line in infinite, by finding slope or intercept you wont be able do anything with them(even though horizontal line doesn't have slope), i suggest use point on line.
so AB is your line [(x,y),(x,y)] and C is on of the point (x,y) and then you need to check if point on the line.
Check Point On a Line
We are given two line segments
AB = line segment from (Ax,Ay) to (Bx,By)
CD = line segment from (Cx,Cy) to (Dx,Dy)
with the same slope.
Order the endpoints E1 < E2 < E3 < E4 such that Ei,x ≤ Ei+1,x and Ei,y ≤ Ei+1,y if Ei,x = Ei+1,x
If E1 and E2 are from different segments, the overlap is the segment from E2 to E3.
There are some degenerate cases:
A < B = C < D
A < C = D < B
A < B = C = D
A = B = C = D
These result in a single point of intersection. I'm not sure if any of those can occur in your system, but if so you'll have to decide whether or not you consider that "overlap" and add special case checks.
The characteristic of two segments of being in the same lines is called collinearity and can be tested calculating the area of the 2 triangles formed by one segment endpoints and, respectively, the endpoints of the other segment. If the area is zero or close to zero below a threshold the segments are collinear.
public static bool AreSegmentsCollinear(Segment a, Segment b, double epsilon)
{
return IsPointCollinear(a, b.Left, epsilon) && IsPointCollinear(a, b.Right, epsilon);
}
public static bool IsPointCollinear(Segment a, Vector2D p, double epsilon)
{
return Math.Abs(GetSignedTriangleArea2(a, p)) <= epsilon;
}
/// <returns>The squared signed area of the triangle formed with endpoints
/// of segment a and point p</returns>
public static double GetSignedTriangleArea2(Segment a, Vector2D p)
{
return (p - a.Left) ^ (a.Right - a.Left);
}
/// <summary>Cross product of vectors in 2D space. NB: it returns a
/// magnitude (scalar), not a vector</summary>
/// <returns>The area of the parallelogram formed with u, v as the edges</returns>
public static Double operator ^(Vector2D u, Vector2D v)
{
return u.X * v.Y - u.Y * v.X;
}
Just to be clear since there seems to be some confusion in the answers, the question being asked is as follows. Given two 2D line segments A and B how do I determine if both of the following are true:
A and B are colinear.
A and B intersect.
Note that there are tolerances involved in both questions i.e. how close to parallel and how near each other do A and B need to be to be considered colinear? How much do they need to overlap to be considered overlapping?
I think to handle such tolerances robustly the best algorithm is to treat the line segments as thin rectangles, where the thickness of the rectangles is a tolerance parameter t1. Let t2 be another tolerance parameter on slopes that are considered parallel. Then the algorithm becomes
If the slope of A and the slope of B are not within t2 of each other return false. To handle vertical lines cleanly, slope can be represented as a unit vector and the test can be on whether the Euclidean distance between the two unit vectors is smaller than t2.
Represent A and B as (non-axis-aligned) rectangles R1 and R2. Where R1 encloses A in the obvious way, i.e. it is length(A) + t1 units long and is t1 units wide with A centered inside it, and R2 analogously encloses B.
Determine if R1 and R2 intersect each other. This can be done relatively efficiently by treating each rectangle as the union of two triangles and testing for triangle-triangle intersections across all combinations of A triangles and B triangles. If there is an intersection return true; otherwise return false.
With lines l1 and l2 given in the following form [x1, y1, x2, y2] the following python code will give the intersection for collinear line segments with any slope.
intersection = line_intersect(l1, l2)
def line_intersect(l1, l2):
"""Find the intersection of two line segments"""
x1, y1, x2, y2 = l1
x3, y3, x4, y4 = l2
x_inter = component_intersect(x1, x2, x3, x4)
y_inter = component_intersect(y1, y2, y3, y4)
return math.sqrt(x_inter**2 + y_inter**2)
def component_intersect(c1, c2, c3, c4):
"""Calculate intersection in one dimension/component"""
# find left endpoints
cl1 = min(c1, c2)
cl2 = min(c3, c4)
# find right endpoints
cr1 = max(c1, c2)
cr2 = max(c3, c4)
# find endpoints of intersection
c_inter_l = max(cl1, cl2)
c_inter_r = min(cr1, cr2)
# calcuate intersection
c_inter = c_inter_r - c_inter_l
c_inter = max(c_inter, 0)
return c_inter

Create a function to generate random points in a parallelogram

I hope someone can help me here, I have been asked to write some code for an Lua script for a game. Firstly i am not an Lua Scripter and I am defiantly no mathematician.
What i need to do is generate random points within a parallelogram, so over time the entire parallelogram becomes filled. I have played with the scripting and had some success with the parallelogram (rectangle) positioned on a straight up and down or at 90 degrees. My problem comes when the parallelogram is rotated.
As you can see in the image, things are made even worse by the coordinates originating at the centre of the map area, and the parallelogram can be positioned anywhere within the map area. The parallelogram itself is defined by 3 pairs of coordinates, start_X and Start_Y, Height_X and Height_Y and finally Width_X and Width_Y. The random points generated need to be within the bounds of these coordinates regardless of position or orientation.
Map coordinates and example parallelogram
An example of coordinates are...
Start_X = 122.226
Start_Y = -523.541
Height_X = 144.113
Height_Y = -536.169
Width_X = 128.089
Width_Y = -513.825
In my script testing i have eliminated the decimals down to .5 as any smaller seems to have no effect on the final outcome. Also in real terms the start width and height could be in any orientation when in final use.
Is there anyone out there with the patients to explain what i need to do to get this working, my maths is pretty basic, so please be gentle.
Thanks for reading and in anticipation of a reply.
Ian
In Pseudocode
a= random number with 0<=a<=1
b= random number with 0<=b<=1
x= Start_X + a*(Width_X-Start_X) + b*(Height_X-Start_X)
y= Start_Y + a*(Width_Y-Start_Y) + b*(Height_Y-Start_Y)
this should make a random point at coordinates x,y within the parallelogram
The idea is that each point inside the parallelogram can be specified by saying how far you go from Start in the direction of the first edge (a) and how far you go in the direction of the second edge (b).
For example, if you have a=0, and b=0, then you do not move at all and are still at Start.
If you have a=1, and b=0, then you move to Width.
If you have a=1, and b=1, then you move to the opposite corner.
You can use something like "texture coordinates", which are in the range [0,1], to generate X,Y for a point inside your parallelogram. Then, you could generate random numbers (u,v) from range [0,1] and get a random point you want.
To explain this better, here is a picture:
The base is formed by vectors v1 and v2. The four points A,B,C,D represent the corners of the parallelogram. You can see the "texture coordinates" (which I will call u,v) of the points in parentheses, for example A is (0,0), D is (1,1). Every point inside the parallelogram will have coordinates within (0,0) and (1,1), for example the center of the parallelogram has coordinates (0.5,0.5).
To get the vectors v1,v2, you need to do vector subtraction: v1 = B - A, v2 = C - A. When you generate random coordinates u,v for a random point r, you can get back the X,Y using this vector formula: r = A + u*v1 + v*v2.
In Lua, you can do this as follows:
-- let's say that you have A,B,C,D defined as the four corners as {x=...,y=...}
-- (actually, you do not need D, as it is D=v1+v2)
-- returns the vector a+b
function add(a,b)
return {x = a.x + b.x, y = a.y + b.y} end
end
-- returns the vector a-b
function sub(a,b)
return {x = a.x - b.x, y = a.y - b.y} end
end
-- returns the vector v1*u + v2*v
function combine(v1,u,v2,v)
return {x = v1.x*u + v2.x*v, y = v1.y*u + v2.y*v}
end
-- returns a random point in parallelogram defined by 2 vectors and start
function randomPoint(s,v1,v2)
local u,v = math.random(), math.random() -- these are in range [0,1]
return add(s, combine(v1,u,v2,v))
end
v1 = sub(B,A) -- your basis vectors v1, v2
v2 = sub(C,A)
r = randomPoint(A,v1,v2) -- this will be in your parallelogram defined by A,B,C
Note that this will not work with your current layout - start, width, height. How do you want to handle rotation with these parameters?

Correct solution for this tensor

I'm implementing the system in this paper and I've come a little unstuck correctly implementing the radial tensor field.
All tensors in this system are of the form given on page 3, section 4
R [ cos(2t), sin(2t); sin(2t), -cos(2t) ]
The radial tensor field is defined as:
R [ yy - xx, -2xy; -2xy, -(yy-xx) ]
In my system I'm only storing R and Theta, since I can calculate the tensor based off just that information. This means I need to calculate R and Theta for the radial tensor. Unfortunately, my attempts at this have failed. Although it looks correct, my solution fails in the top left and bottom right quadrants.
Addendum: Following on from discussion in the comments about the image of the system not working, I'll put some hard numbers here too.
The entire tensor field is 800x480, the center point is at { 400, 240 }, and we're using the standard graphics coordinate system with a negative y axis (ie. origin in the top left).
At { 400, 240 }, the tensor is R = 0, T = 0
At { 200, 120 }, the tensor is R = 2.95936E+9, T = 2.111216
At { 600, 120 }, the tensor is R = 2.95936E+9, T = 1.03037679
I can easily sample any more points which you think may help.
The code I'm using to calculate values is:
float x = i - center.X;
float xSqr = x * x;
float y = j - center.Y;
float ySqr = y * y;
float r = (float)Math.Pow(xSqr + ySqr, 2);
float theta = (float)Math.Atan2((-2 * x * y), (ySqr - xSqr)) / 2;
if (theta < 0)
theta += MathHelper.Pi;
Evidently you are comparing formulas (1) and (2) of the paper. Note the scalar multiple l = || (u_x,u_y) || in formula (1), and identify that with R early in the section. This factor is implicit in formula (2), so to make them match we have to factor R out.
Formula (2) works with an offset from the "center" (x0,y0) of the radial map:
x = xp - x0
y = yp - y0
to form the given 2x2 matrix:
y^2 - x^2 -2xy
-2xy -(y^2 - x^2)
We need to factor out a scalar R from this matrix to get a traceless orthogonal 2x2 matrix as in formula (1):
cos(2t) sin(2t)
sin(2t) -cos(2t)
Since cos^2(2t) + sin^2(2t) = 1 the factor R can be identified as:
R = (y^2 - x^2)^2 + (-2xy)^2 = (x^2 + y^2)^2
leaving a traceless orthogonal 2x2 matrix:
C S
S -C
from which the angle 'tan(2t) = S/C` can be extracted by an inverse trig function.
Well, almost. As belisarius warns, we need to check that angle t is in the correct quadrant. The authors of the paper write at the beginning of Sec. 4 that their "t" (which refers to the tensor) depends on R >= 0 and theta (your t) lying in [0,2pi) according to the formula R [ cos(2t), sin(2t); sin(2t) -cos(2t) ].
Since sine and cosine have period 2pi, t (theta) is only uniquely determined up to an interval of length pi. I suspect the authors meant to write either that 2t lies in [0,2pi) or more simply that t lies in [0,pi). belisarius suggestion to use "the atan2 equivalent" will avoid any division by zero. We may (if the function returns a negative value) need to add pi so that t >= 0. This amounts to adding 2pi to 2t, so it doesn't affect the signs of the entries in the traceless orthogonal matrix (since 'R >= 0` the pattern of signs should agree in formulas (1) and (2) ).