Matlab - Distances of two lines - arrays

I have two lines, one straight and one curvy. Both have an arbitrary number of x and y values defining the lines - the number of x and y values are not the same for either line. I am attempting to get separate distances of points between the curved line coordinates and the straight line coordinates. You can think of discrete integration to get a better picture of what I'm talking about, something along the lines of this: http://www.scientific-solutions.ch/tech/origin/products/images/calculus_integral.gif
By adding the different distances, I would get the area. The part on which I am stuck is the actual synchronization of the points. I can simply compare the x and y values of the straight and curve coordinates every ten indices for example because the curved coordinates are time dependent (as in the points do not change at a general rate). I need a way to synchronize the actual coordinates of the two sets of points. I thought about interpolating both sets of points to a specific number of points, but again, the time dependence of the curved set of points makes that solution void.
Could someone please suggest a good way of doing this, outlining the basics? I really appreciate the help.
Code to be tried (pseudo):
xLine = [value1 value2 ...]
yLine = [value1 value2 ...]
xCurve = [value1 value2 ...]
yCurve = [value1 value2 ...]
xLineInterpolate = %interpolate of every 10 points of x until a certain value. same with yLineInterpolate, xCurveInterpolate and yCurveInterpolate.
Then, I could just take the same index from each array and do some algebra to get the distance. My worry is that my line values increase at a constant rate whereas my curve values sometimes do not change (x and y values have different rates of change) and sometimes do. Would such an interpolation method be wrong then?

If I understand correctly, you want to know the distance between a straight line and a curve. The easiest way is to perform a coordinate transformation such that the straight line is the new x-axis. In that frame, the y-values of the curved line are the distances you seek.
This coordinate transformation is equal to a rotation and a translation, as in the following:
% estimate coefficients for straight line
sol = [x1 ones(size(x1))] \ y1;
m = sol(1); %# slope
b = sol(2); %# y-offset at x=0
% shift curved line down by b
% (makes the straight line go through the origin)
y2 = y2 - b;
% rotate the curved line by -atan(m)
% (makes the straight line run parallel to the x-axis)
a = -atan(m);
R = [+cos(a) -sin(a)
+sin(a) +cos(a)];
XY = R*[x2; y2];
% the distances are then the values of y3.
x3 = XY(1,:);
y3 = XY(2,:);

You need to use interpolation. I don't see how the time-dependence is relevant here - perhaps you are thinking of fitting a straight line to both curves? That's a bad idea.
You can do a simple interpolation for any curve just by assuming that every two adjacent points are connected by a straight line. This can be shown to be a reasonable approximation for the curve.
So, let's say you are looking at (x1,y1) and (x2,y2) which are adjacent to each other and now you choose an x3 that is between x1 and x2 (x1 < x2 < x3), and want to find the y3 value.
A simple way to find y3 is the following:
p=(x3-x1)/(x2-x1)
y3=y1+p*(y2-y1)
The idea is that p shows the relative position between x1 and x2 (0.5 would be the middle, for example), and then you use p as the relative position between y1 and y2.

Related

Resampling two vectors with interp1 or spline

Situation:
I was trying to compare two signal vectors (y1 & y2 with time vectors x1 & x2) with different lengths (len(y1)=1000>len(y2)=800). For this, I followed the main piece of advice given hardly everywhere: to use interp1 or spline. In order to 'expand' y2 towards y1 in number of samples through an interpolation.
So I want:
length(y1)=length(y2_interp)
However, in these functions you have to give the points 'x' where to interpolate (xq), so I generate a vector with the resampled points I want to compute:
xq = x2(1):(length(x2))/length(x1):x2(length(x2));
y2_interp = interp1(x2,y2,xq,'spline'); % or spline method directly
RMS = rms(y1-y2_interp)
The problem:
When I resample the x vector in 'xq' variable, as the faction of lengths is not an integer it gives me not the same length for 'y2_interp' as 'y1'. I cannot round it for the same problem.
I tried interpolate using the 'resample' function:
y2_interp=resample(y2,length(y1),length(y2),n);
But I get an aliasing problem and I want to avoid filters if possible. And if n=0 (no filters) I get some sampling problems and more RMS.
The two vectors are quite long, so my misalignment is just of 2 or 3 points.
What I'm looking for:
I would like to find a way of interpolating one vector but having as a reference the length of another one, and not the points where I want to interpolate.
I hope I have explained it well... Maybe I have some misconception. It's more than i'm curious about any possible idea.
Thanks!!
The function you are looking for here is linspace
To get an evenly spaced vector xq with the same endpoints as x2 but the same length as x1:
xq = (x2(1),x2(end),length(x1));
It is not sufficient to interpolate y2 to get the right number of samples, the samples should be at locations corresponding to samples of y1.
Thus, you want to interpolate y2 at the x-coordinates where you have samples for y1, which is given by x1:
y2_interp = interp1(x2,y2,x1,'spline');
RMS = rms(y1-y2_interp)

Linear interpolation: calculate correction based on 2D table

I try to do a thing that should be nothing more than a two-dimensional, linear interpolation but currently I fail finding the correct approach. To describe the problem a bit simplified: there is a drawing area with a size of 3000x3000 pixels where I have to draw e.g. a horizontal line. To do that I'm drawing dots or short lines from every pixel position to the next pixel position which then forms a line.
Now a correction has to be applied to the whole thing where correction information can be found in a (for this example simplified) 4 by 4 array, where every element contains a pair of coordinates describing the values after correction. So a neutral array (with no correction) would look like this:
0,0 1000,0 2000,0 3000,0
0,1000 1000,1000 2000,1000 3000,1000
0,2000 1000,2000 2000,2000 3000,2000
0,3000 1000,3000 2000,3000 3000,3000
A real correction table would contain other coordinates describing the correction to be done:
So as input data I have the coordinates of points on the line without correction, the fields values without correction and the correction data. But how can I calculate the lines points now applying the correction values to it so that a distorted line is drawn like shown in right side if the image? My current approach with two separate linear interpolations for X and Y does not work, there the Y-position jumps on a cells border but does not change smoothly within a cell.
So...any ideas how this could be done?
You have to agree on an interpolation method first. I would suggest either bilinear or barycentric interpolation. In one of my previous posts I visualized the difference between both methods.
I'll concentrate on the bilinear interpolation. We want to transform any point within a cell to its corrected point. Therefore, all points could be transformed separately.
We need the interpolation parameters u and v for the point (x, y). Because we have an axis-aligned grid, this is pretty simple:
u = (x - leftCellEdge) / (rightCellEdge - leftCellEdge)
v = (y - bottomCellEdge) / (topCellEdge - bottomCellEdge)
We could reconstruct the point by bilinear interpolation:
p2 p4
x----x
| o |
x----x
p1 p3
o = (1 - u) * ((1 - v) * p1 + v * p2) + u * ((1 - v) * p3 + v * p4)
Now, the same formula can be used for the corrected points. If you use the original points p1 through p4, you'll get the uncorrected line point. If you use the corrected cell points for p1 through p4, you'll get the corrected line point.

I need to translate 3d points relative to a triangle as if the triangle was somewhere else

I posted this on twitter a while ago but seeing how none of my followers appears to be a math/programming genius, I'll try my luck here as well. I got here because I found this which might contain part of my solution.
I described my problem in the following pdf document, containing a picture of what I'm trying to achieve.
To give some more details, I divided the pentagon's of a dodecahedron (12 pentagons) into triangles (5/pentagon, 60 triangles in total), then collected a set of data points relative to each of these triangles.
The idea is to generate terrain meshes for each individual triangle.
To do so, the data must be represented flat, in a 32K x 32K square (idTech4 Megatexture)
I have vaguely heard of transformation matrices, which when set up properly, could do the trick of passing all the data points trough them to have them show up in the right place.
I looked at this source code here but I don't understand how I'm supposed to get the points in and/or out of there, not to mention how to do the setup so I can present each point in turn and get the result point back.
I got as fas as identifying the point that belongs in the back right corner. All my 3D points are originally stored in latitude / longitude pairs. I retrieve the 3D vectors this way:
coord getcoord(point* p)
{
coord c;
c.x=cos(p->lat*pi/180.l) * cos(p->lon*pi/180.l);
c.y=cos(p->lat*pi/180.l) * sin(p->lon*pi/180.l);
c.z=sin(p->lat*pi/180.l);
return c;
};
My thought is that if I can find the center of my triangle, and discover how to offset my angles so the vector from the center of my sphere to the middle of the triangle moves to 90N then my points would already be in the right plane if I rotated them all along the same angles. If I then convert them all to 3d and subtracti the radius from y, they'll be at the correct y position as well.
Then all I'd need to do is the rotation, the scaling, and the moving to the final position.
There are several kinds of 'centers' for a triangle, I think the one I need is the one that is equidistant to the corners of the triangle (Circumcenter?)
But then there might be an easier approach to the whole problem so while I continue my own research, perhaps some of you can help pointing me in the right direction.
It appears as if some sample data is in order, here are a few of these triangles in obj file format:
v 0.000000 0.000000 3396.000000
v 2061.582356 0.000000 2698.646733
v 637.063983 1960.681333 2698.646733
f 1 2 3
And another:
v -938.631230 2888.810129 1518.737455
v 637.063983 1960.681333 2698.646733
v 1030.791271 3172.449325 637.064076
f 1 2 3
You will notice that each point is at a distance of 3396 from 0,0,0
I mentioned 'on the sphere' meaning that the face away from the center of the sphere is the face that needs to become the 'top' when translated into the square.
Theoretically all these triangles should in fact have identical sizes, but due to rounding errors in the math that generated them, this might not be entirely true.
If I'm not mistaken I already took measures to ensure that the first point you see here is always the one opposite the longest border, so it's the one that should go in the far left corner (testing the above 2 samples confirms this, but I'm measuring anyway just to be sure)
Both legs leading away from this point should theoretically have the same length as well, but again rounding errors might slightly offset that.
If I've done it correctly then the longer side is 1,113587 times longer than the 2 shorter sides. Assuming those are identical, then doing some goal seeking in excel, I can deduct that the final points, assuming I was just translating this triangle, should look like:
v 16384.000000 0.000000 16384.000000
v -16384.000000 0.000000 9916.165306
v 9916.165306 0.000000 -16384.000000
f 1 2 3
So I need to setup the matrix to do this transformation, preferably using the 4x4 matrix as explained below.
I would recommend using transform matrices. The 3d transform matrix is a 4x4 data structure which describes a translation and rotation (and possibly a scale). Once you have a matrix you can transform a point like so
result.x = (tmp->pt.x * m->element[0][0]) +
(tmp->pt.y * m->element[1][0]) +
(tmp->pt.z * m->element[2][0]) +
m->element[3][0];
result.y = (tmp->pt.x * m->element[0][1]) +
(tmp->pt.y * m->element[1][1]) +
(tmp->pt.z * m->element[2][1]) +
m->element[3][1];
result.z = (tmp->pt.x * m->element[0][2]) +
(tmp->pt.y * m->element[1][2]) +
(tmp->pt.z * m->element[2][2]) +
m->element[3][2];
int w = (tmp->pt.x * m->element[0][3]) + (tmp->pt.y * m->element[1][3])
+ (tmp->pt.z * m->element[2][3]) + m->element[3][3];
if (w!=0 || w!=1)
result.x/=w; result.y/=w; result.z/=w;
This will transform the 3D point pt by the matrix m. If you now a little matrix math you'll see i'm just multiplying my origin point as a vector against the matrix (and doing a little normalization if it is a skew matrix.) Matrices can be multiplied together to form complicated transformations so they are very useful.
For details on making matrices suggest reading this link.
http://en.wikipedia.org/wiki/Transformation_matrix

MATLAB: Interpolating to find the x value of the intersection between a line and a curve

Here is the graph I currently have
:
The Dotted Blue line represented the y value that corresponds to the x value I am looking for. I am trying to find the x values of the line's intersections with the blue curve(Upper).Since the interesections do not fall on a point that has already been defined, we need to interpolate a point that falls onto the Upper plot.
Here is the information I have:
LineValue - The y value of the intersection and the value of the dotted line( y = LineValue)
Frequency - an array containing the x value coordinates seen on this plot. The interpolated values of Frequency that corresponds to LineValue are what we are looking for
Upper/Lower - arrays containing the y value info for this graph
This solution is an improvement on Amro's answer. Instead of using fzero you can simply calculate the intersection of the line by looking for transition in the first-difference of the series created by a logical comparison to LineValue. So, using Amro's sample data:
>> x = linspace(-100,100,100);
>> y = 1-2.*exp(-0.5*x.^2./20)./(2*pi) + randn(size(x))*0.002;
>> LineValue = 0.8;
Find the starting indices of those segments of consecutive points that exceed LineValue:
>> idx = find(diff(y >= LineValue))
idx =
48 52
You can then calculate the x positions of the intersection points using weighted averages (i.e. linear interpolation):
>> x2 = x(idx) + (LineValue - y(idx)) .* (x(idx+1) - x(idx)) ./ (y(idx+1) - y(idx))
x2 =
-4.24568579887939 4.28720287203057
Plot these up to verify the results:
>> figure;
>> plot(x, y, 'b.-', x2, LineValue, 'go', [x(1) x(end)], LineValue*[1 1], 'k:');
The advantages of this approach are:
The determination of the intersection points is vectorized so will work regardless of the number of intersection points.
Determining the intersection points arithmetically is presumably faster than using fzero.
Example solution using FZERO:
%# data resembling your curve
x = linspace(-100,100,100);
f = #(x) 1-2.*exp(-0.5*x.^2./20)./(2*pi) + randn(size(x))*0.002;
VALUE = 0.8;
%# solve f(x)=VALUE
z1 = fzero(#(x)f(x)-VALUE, -10); %# find solution near x=-10
z2 = fzero(#(x)f(x)-VALUE, 10); %# find solution near x=+10
%# plot
plot(x,f(x),'b.-'), hold on
plot(z1, VALUE, 'go', z2, VALUE, 'go')
line(xlim(), [VALUE VALUE], 'Color',[0.4 0.4 0.4], 'LineStyle',':')
hold off
Are the step sizes in your data series the same?
Is the governing equation assumed to be cubic, sinuisoidal, etc..?
doc interpl
Find the zero crossings

WPF: Finding an element along a path

I have not marked this question Answered yet.
The current accepted answer got accepted automatically because of the Bounty Time-Limit
With reference to this programming game I am currently building.
As you can see from the above link, I am currently building a game in where user-programmable robots fight autonomously in an arena.
Now, I need a way to detect if a robot has detected another robot in a particular angle (depending on where the turret may be facing):
alt text http://img21.imageshack.us/img21/7839/robotdetectionrg5.jpg
As you can see from the above image, I have drawn a kind of point-of-view of a tank in which I now need to emulate in my game, as to check each point in it to see if another robot is in view.
The bots are just canvases that are constantly translating on the Battle Arena (another canvas).
I know the heading the turret (the way it will be currently facing), and with that, I need to find if there are any bots in its path(and the path should be defined in kind of 'viewpoint' manner, depicted in the image above in the form of the red 'triangle'. I hope the image makes things more clear to what I am trying to convey.
I hope that someone can guide me to what math is involved in achieving this problem.
[UPDATE]
I have tried the calculations that you have told me, but it's not working properly, since as you can see from the image, bot1 shouldn't be able to see Bot2 . Here is an example :
alt text http://img12.imageshack.us/img12/7416/examplebattle2.png
In the above scenario, Bot 1 is checking if he can see Bot 2. Here are the details (according to Waylon Flinn's answer):
angleOfSight = 0.69813170079773179 //in radians (40 degrees)
orientation = 3.3 //Bot1's current heading (191 degrees)
x1 = 518 //Bot1's Center X
y1 = 277 //Bot1's Center Y
x2 = 276 //Bot2's Center X
y2 = 308 //Bot2's Center Y
cx = x2 - x1 = 276 - 518 = -242
cy = y2 - y1 = 308 - 277 = 31
azimuth = Math.Atan2(cy, cx) = 3.0141873380511295
canHit = (azimuth < orientation + angleOfSight/2) && (azimuth > orientation - angleOfSight/2)
= (3.0141873380511295 < 3.3 + 0.349065850398865895) && (3.0141873380511295 > 3.3 - 0.349065850398865895)
= true
According to the above calculations, Bot1 can see Bot2, but as you can see from the image, that is not possible, since they are facing different directions.
What am I doing wrong in the above calculations?
The angle between the robots is arctan(x-distance, y-distance) (most platforms provide this 2-argument arctan that does the angle adjustment for you. You then just have to check whether this angle is less than some number away from the current heading.
Edit 2020: Here's a much more complete analysis based on the updated example code in the question and a now-deleted imageshack image.
Atan2: The key function you need to find an angle between two points is atan2. This takes a Y-coordinate and X-coordinate of a vector and returns the angle between that vector and the positive X axis. The value will always be wrapped to lie between -Pi and Pi.
Heading vs Orientation: atan2, and in general all your math functions, work in the "mathematical standard coordinate system", which means an angle of "0" corresponds to directly east, and angles increase counterclockwise. Thus, an "mathematical angle" of Pi / 2 as given by atan2(1, 0) means an orientation of "90 degrees counterclockwise from due east", which matches the point (x=0, y=1). "Heading" is a navigational idea that expresses orientation is a clockwise angle from due north.
Analysis: In the now-deleted imageshack image, your "heading" of 191 degrees corresponded to a south-south-west direction. This actually an trigonometric "orientation" of -101 degrees, or -1.76. The first issue in the updated code is therefore conflating "heading" and "orientation". you can get the latter from the former by orientation_degrees = 90 - heading_degrees or orientation_radians = Math.PI / 2 - heading_radians, or alternatively you could specify input orientations in the mathematical coordinate system rather than the nautical heading coordinate system.
Checking that an angle lies between two others: Checking that an vector lies between two other vectors is not as simple as checking that the numeric angle value is between, because of the way the angles wrap at Pi/-Pi.
Analysis: in your example, the orientation is 3.3, the right edge of view is orientation 2.95, the left edge of view is 3.65. The calculated azimith is 3.0141873380511295, which happens to be correct (it does lie between). However, this would fail for azimuth values like -3, which should be calculated as "hit". See Calculating if an angle is between two angles for solutions.
Calculate the relative angle and distance of each robot relative to the current one. If the angle is within some threshold of the current heading and within the max view range, then it can see it.
The only tricky thing will be handling the boundary case where the angle goes from 2pi radians to 0.
Something like this within your bot's class (C# code):
/// <summary>
/// Check to see if another bot is visible from this bot's point of view.
/// </summary>
/// <param name="other">The other bot to look for.</param>
/// <returns>True iff <paramref name="other"/> is visible for this bot with the current turret angle.</returns>
private bool Sees(Bot other)
{
// Get the actual angle of the tangent between the bots.
var actualAngle = Math.Atan2(this.X - other.X, this.Y - other.Y) * 180/Math.PI + 360;
// Compare that angle to a the turret angle +/- the field of vision.
var minVisibleAngle = (actualAngle - (FOV_ANGLE / 2) + 360);
var maxVisibleAngle = (actualAngle + (FOV_ANGLE / 2) + 360);
if (this.TurretAngle >= minVisibleAngle && this.TurretAngle <= maxVisibleAngle)
{
return true;
}
return false;
}
Notes:
The +360's are there to force any negative angles to their corresponding positive values and to shift the boundary case of angle 0 to somewhere easier to range test.
This might be doable using only radian angles but I think they're dirty and hard to read :/
See the Math.Atan2 documentation for more details.
I highly recommend looking into the XNA Framework, as it's created with game design in mind. However, it doesn't use WPF.
This assumes that:
there are no obstacles to obstruct the view
Bot class has X and Y properties
The X and Y properties are at the center of the bot.
Bot class a TurretAngle property which denotes the turret's positive angle relative to the x-axis, counterclockwise.
Bot class has a static const angle called FOV_ANGLE denoting the turret's field of vision.
Disclaimer: This is not tested or even checked to compile, adapt it as necessary.
A couple of suggestions after implementing something similar (a long time ago!):
The following assumes that you are looping through all bots on the battlefield (not a particularly nice practice, but quick and easy to get something working!)
1) Its a lot easier to check if a bot is in range then if it can currently be seen within the FOV e.g.
int range = Math.sqrt( Math.abs(my.Location.X - bots.Location.X)^2 +
Math.abs(my.Location.Y - bots.Location.Y)^2 );
if (range < maxRange)
{
// check for FOV
}
This ensures that it can potentially short-cuircuit a lot of FOV checking and speed up the process of running the simulation. As a caveat, you could have some randomness here to make it more interesting, such that after a certain distance the chance to see is linearly proportional to the range of the bot.
2) This article seems to have the FOV calculation stuff on it.
3) As an AI graduate ... nave you tried Neural Networks, you could train them to recognise whether or not a robot is in range and a valid target. This would negate any horribly complex and convoluted maths! You could have a multi layer perceptron [1], [2] feed in the bots co-ordinates and the targets cordinates and recieve a nice fire/no-fire decision at the end. WARNING: I feel obliged to tell you that this methodology is not the easiest to achieve and can be horribly frustrating when it goes wrong. Due to the (simle) non-deterministic nature of this form of algorithm, debugging can be a pain. Plus you will need some form of learning either Back Propogation (with training cases) or a Genetic Algorithm (another complex process to perfect)! Given the choice I would use Number 3, but its no for everyone!
It can be quite easily achieved with the use of a concept in vector math called dot product.
http://en.wikipedia.org/wiki/Dot_product
It may look intimidating, but it's not that bad. This is the most correct way to deal with your FOV issue, and the beauty is that the same math works whether you are dealing with 2D or 3D (that's when you know the solution is correct).
(NOTE: If anything is not clear, just ask in the comment section and I will fill in the missing links.)
Steps:
1) You need two vectors, one is the heading vector of the main tank. Another vector you need is derived from the position of the tank in question and the main tank.
For our discussion, let's assume the heading vector for main tank is (ax, ay) and vector between main tank's position and target tank is (bx, by). For example, if main tank is at location (20, 30) and target tank is at (45, 62), then vector b = (45 - 20, 62 - 30) = (25, 32).
Again, for purpose of discussion, let's assume main tank's heading vector is (3,4).
The main goal here is to find the angle between these two vectors, and dot product can help you get that.
2) Dot product is defined as
a * b = |a||b| cos(angle)
read as a (dot product) b since a and b are not numbers, they are vectors.
3) or expressed another way (after some algebraic manipulation):
angle = acos((a * b) / |a||b|)
angle is the angle between the two vectors a and b, so this info alone can tell you whether one tank can see another or not.
|a| is the magnitude of the vector a, which according to the Pythagoras Theorem, is just sqrt(ax * ax + ay * ay), same goes for |b|.
Now the question comes, how do you find out a * b (a dot product b) in order to find the angle.
4) Here comes the rescue. Turns out that dot product can also be expressed as below:
a * b = ax * bx + ay * by
So angle = acos((ax * bx + ay * by) / |a||b|)
If the angle is less than half of your FOV, then the tank in question is in view. Otherwise it's not.
So using the example numbers above:
Based on our example numbers:
a = (3, 4)
b = (25, 32)
|a| = sqrt(3 * 3 + 4 * 4)
|b| = sqrt(25 * 25 + 32 * 32)
angle = acos((20 * 25 + 30 * 32) /|a||b|
(Be sure to convert the resulting angle to degree or radian as appropriate before comparing it to your FOV)
This will tell you if the center of canvas2 can be hit by canvas1. If you want to account for the width of canvas2 it gets a little more complicated. In a nutshell, you would have to do two checks, one for each of the relevant corners of canvas2, instead of one check on the center.
/// assumming canvas1 is firing on canvas2
// positions of canvas1 and canvas2, respectively
// (you're probably tracking these in your Tank objects)
int x1, y1, x2, y2;
// orientation of canvas1 (angle)
// (you're probably tracking this in your Tank objects, too)
double orientation;
// angle available for firing
// (ditto, Tank object)
double angleOfSight;
// vector from canvas1 to canvas2
int cx, cy;
// angle of vector between canvas1 and canvas2
double azimuth;
// can canvas1 hit the center of canvas2?
bool canHit;
// find the vector from canvas1 to canvas2
cx = x2 - x1;
cy = y2 - y1;
// calculate the angle of the vector
azimuth = Math.Atan2(cy, cx);
// correct for Atan range (-pi, pi)
if(azimuth < 0) azimuth += 2*Math.PI;
// determine if canvas1 can hit canvas2
// can eliminate the and (&&) with Math.Abs but this seems more instructive
canHit = (azimuth < orientation + angleOfSight) &&
(azimuth > orientation - angleOfSight);
Looking at both of your questions I'm thinking you can solve this problem using the math provided, you then have to solve many other issues around collision detection, firing bullets etc. These are non trivial to solve, especially if your bots aren't square. I'd recommend looking at physics engines - farseer on codeplex is a good WPF example, but this makes it into a project way bigger than a high school dev task.
Best advice I got for high marks, do something simple really well, don't part deliver something brilliant.
Does your turret really have that wide of a firing pattern? The path a bullet takes would be a straight line and it would not get bigger as it travels. You should have a simple vector in the direction of the the turret representing the turrets kill zone. Each tank would have a bounding circle representing their vulnerable area. Then you can proceed the way they do with ray tracing. A simple ray / circle intersection. Look at section 3 of the document Intersection of Linear and Circular Components in 2D.
Your updated problem seems to come from different "zero" directions of orientation and azimuth: an orientation of 0 seems to mean "straight up", but an azimuth of 0 "straight right".

Resources