using a loop to change color of pixels according to calculations - jython

I am just starting to learn jython, and just have a question which I cannot seem to get right.
From my text, I am to create a picture that is 640 x 480 pixels, and then, using a loop, pixel by pixel set the color to a calculation for r, g, b which we have already been given.
I can create a picture, I can set variables, however I cannot seem to go any further in creating a loop to set each pixel colour.
I know its only simple, but just wandering if anyone can help me out here.

xrange() will create a generator which yields integers in a range. for will loop once per element of an iterable.
for row in xrange(480):
for col in xrange(640):
...

This may help you to iterate through the pixels.
picture = makeEmptyPicture(400,200)
pixels = getPixels(picture)
#make an empty picture and get the pixels
for px in getPixels(picture):
x=getX(px)
y=getY(px)
r = (sin(x * radian * id[1]) * cos(y * radian * id[4]) + 1) * ord(StringID[0]) * 2.5
g = (sin(x * radian * id[2]) * cos(y * radian * id[5]) + 1) * ord(StringID[0]) * 2.5
b = (sin(x * radian * id[3]) * cos(y * radian * id[6]) + 1) * ord(StringID[0]) * 2.5
newColor=makeColor(255 - r, 255 - g, 255 - b)
setColor(px, newColor)
show(picture)
repaint(picture)

Related

Compute FOVX when FOVY > 180°

This is related to this question. The formula fieldOfViewX = 2 * atan(tan(fieldOfViewY * 0.5) * aspect) works but when FOVY > 180° for fisheyes camera, it doesn't work anymore. It is possible to adapt this formula to make it work?

Using vDSP_biquad as a one pole filter

I'd like to be able to use the vDSP_biquad function as a one pole filter.
My one pole filter looks like this :
output[i] = onePole->z1 = input[i] * onePole->a0 + onePole->z1 * onePole->b1;
where
b1 = exp(-2.0 * M_PI * (_frequency / sampleRate));
a0 = 1.0 - b1;
This one pole works great, but of course it's not optimized, which is why I'd like to use the Accelerate Framework to speed it up.
Because vDSP_biquad uses the Direct Form II of the biquad implementation, it seems to me I should be able to set the coefficients to use it as a one-pole filter. https://en.wikipedia.org/wiki/Digital_biquad_filter#Direct_form_2
filter->omega = 2 * M_PI * freq / sampleRate;
filter->b1 = exp(-filter->omega);
filter->b0 = 1 - filter->b1;
filter->b2 = 0;
filter->a1 = 0;
filter->a2 = 0;
However, this does not work as a one pole filter. (The implementation of biquad is fine, I use it for many other filter types, it's just these coefficients don't have the desired effect).
What am I doing wrong?
Also open to hearing other ways to optimize a one-pole filter with Accelerate or otherwise.
The formula in the Apple docs is:
y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2]
In your above code, you're using b1 which is two inputs ago. For a one-pole, you'll need to use the previous output, y[n-1].
So I think the coefficients you want are:
a1 = -exp(-2.0 * M_PI * (_frequency / sampleRate))
b0 = 1.0 + a1

Can I use the Postgres functions to find points inside a rotating rectangle of fixed size?

I'm using Postgres 9.5 and I've just installed PostGIS for some extended functions. I have a table with (x,y) points and I want to find the rectangle that fits the maximum number of points. The constraint is that the rectangle side lenghts are fixed. So far I'm counting how many points are in the box without rotation. My points are centered around the origin, (0,0).
SELECT Sum(CASE
WHEN x > -5
AND x < 5
AND y > -10
AND y < 10 THEN 1
ELSE 0
END) AS inside_points,
Count(1) AS total_points
FROM track_t;
This query gives me the count of points inside a rectangle with origin (0,0) and lenghts x = 10 and y = 20.
From here I would create a helper table of rotated rectangle corner points (angle, x1, y1, x2, y2), then cross join to my data, and count over the points per angle, while GROUP BY angle. Then I can select which angle gives me the most points inside the rectangle.
But this seems a little old fashioned, and perhaps non-performant. Additionally, counting points inside a rotated rectangle is not a trivial calculation.
Are there more efficient and elegant ways, perhaps using Postgres Geometric Datatypes or PostGIS Box2D, to rotate a rectangle with fixed side lenghts, and then to count the number of points inside? The geometric functions look good, but they seem to provide minimum bounding boxes and not the other way around.
In addition to Postgresql, I'm using a Python framework that could be used in case SQL can't make this work.
Update: One thing I tried is to use Geometric Types, specifically BOX
SELECT deg, Box(Point(-5, -10), Point(5, 10)) * Point(1, Radians(deg))
FROM Generate_series(0, 360, 90) AS deg
Unforunately, the Rotate function by a Point doesn't work for Polygons.
I ended up by generating rectangle vertices, rotating those vertices, and then comparing the area of the rectangle (constant) with the area of the 4 triangles that are made by including the test point.
This technique is based on the parsimonious answer:
Make triangle. Suppose, abcd is the rectangle and x is the point then if area(abx)+area(bcx)+area(cdx)+area(dax) equals area(abcd) then the point is inside it.
The rectangles are defined by
A bottom left (-x/2,-y/2)
B top left (-x/2,+y/2)
C top right (+x/2,+y/2)
D bottom right (+x/2,-y/2)
This code then checks if point (qx,qy) is inside a rectangle of width x=10 and height y=20, which is rotated around the origin (0,0) by an angle with range of 0 to 180, by 10 degrees.
Here's the code. It's taking 9 minutes to check 750k points, so there is definite room for improvement. Additionally, It can be parallelized once I upgrade to 9.6
with t as (select 10*0.5 as x, 20*0.5 as y, 17.0 as qx, -3.0 as qy)
select
z.angle
-- ABC area
--,abs(0.5*(z.ax*(z.by-z.cy)+z.bx*(z.cy-z.ay)+z.cx*(z.ay-z.by)))
-- CDA area
--,abs(0.5*(z.cx*(z.dy-z.ay)+z.dx*(z.ay-z.cy)+z.ax*(z.cy-z.dy)))
-- ABCD area
,abs(0.5*(z.ax*(z.by-z.cy)+z.bx*(z.cy-z.ay)+z.cx*(z.ay-z.by))) + abs(0.5*(z.cx*(z.dy-z.ay)+z.dx*(z.ay-z.cy)+z.ax*(z.cy-z.dy))) as abcd_area
-- ABQ area
--,abs(0.5*(z.ax*(z.by-z.qx)+z.bx*(z.qy-z.ay)+z.qx*(z.ay-z.by)))
-- BCQ area
--,abs(0.5*(z.bx*(z.cy-z.qx)+z.cx*(z.qy-z.by)+z.qx*(z.by-z.cy)))
-- CDQ area
--,abs(0.5*(z.cx*(z.dy-z.qx)+z.dx*(z.qy-z.cy)+z.qx*(z.cy-z.dy)))
-- DAQ area
--,abs(0.5*(z.dx*(z.ay-z.qx)+z.ax*(z.qy-z.dy)+z.qx*(z.dy-z.ay)))
-- total area of triangles with question point (ABQ + BCQ + CDQ + DAQ)
,abs(0.5*(z.ax*(z.by-z.qx)+z.bx*(z.qy-z.ay)+z.qx*(z.ay-z.by)))
+ abs(0.5*(z.bx*(z.cy-z.qx)+z.cx*(z.qy-z.by)+z.qx*(z.by-z.cy)))
+ abs(0.5*(z.cx*(z.dy-z.qx)+z.dx*(z.qy-z.cy)+z.qx*(z.cy-z.dy)))
+ abs(0.5*(z.dx*(z.ay-z.qx)+z.ax*(z.qy-z.dy)+z.qx*(z.dy-z.ay))) as point_area
from
(
SELECT
a.id as angle
-- bottom left (A)
,(-t.x) * cos(radians(a.id)) - (-t.y) * sin(radians(a.id)) as ax
,(-t.x) * sin(radians(a.id)) + (-t.y) * cos(radians(a.id)) as ay
--top left (B)
,(-t.x) * cos(radians(a.id)) - (t.y) * sin(radians(a.id)) as bx
,(-t.x) * sin(radians(a.id)) + (t.y) * cos(radians(a.id)) as by
--top right (C)
,(t.x) * cos(radians(a.id)) - (t.y) * sin(radians(a.id)) as cx
,(t.x) * sin(radians(a.id)) + (t.y) * cos(radians(a.id)) as cy
--bottom right (D)
,(t.x) * cos(radians(a.id)) - (-t.y) * sin(radians(a.id)) as dx
,(t.x) * sin(radians(a.id)) + (-t.y) * cos(radians(a.id)) as dy
-- point to check (Q)
,t.qx as qx
,t.qy as qy
FROM generate_series(0,180,10) AS a(id), t
) z
;
the results then are
angle;abcd_area;point_area
0;200;340
10;200;360.6646055963
20;200;373.409049054212
30;200;377.846096908265
40;200;373.84093170467
50;200;361.515248361426
60;200;341.243556529821
70;200;313.641801308188
80;200;279.548648061772
90;200;240
*100;200;200*
*110;200;200*
*120;200;200*
*130;200;200*
*140;200;200*
150;200;237.846096908265
160;200;277.643408923024
170;200;312.04311584956
180;200;340
Where the rotations of angles 100, 110, 120, 130 and 140 degrees then includes the test-point (indicated with *)

Converting an equation to code

I have an equation that can be used to find the gun elevation for artillery, using the range, muzzle velocity and change in altitude in a game called Arma 3. The equation looks like this:
With g being the acceleration due to gravity (9.80665), V being the muzzle velocity, X being the range and Y being the change in altitude (called DAlt in my code).
I'm trying to convert it to a line of code so that I can make a program to calculate the elevation based on given coordinates. However I'm having trouble with it. I currently have this:
If rdoLow.Checked = True Then
Elevation = Math.Atan(((Velocity ^ 2) - (Math.Sqrt((Velocity ^ 4) - (G) * (G * (Range ^ 2) + (2 * DAlt * (Velocity ^ 2)))))) / G * Range)
Else
Elevation = Math.Atan(((Velocity ^ 2) + (Math.Sqrt((Velocity ^ 4) - (G) * (G * (Range ^ 2) + 2 * DAlt * (Velocity ^ 2))))) / G * Range)
End If
Which isn't particularly nice looking but as far as I can tell, it should work. However when I put in the values that the video I got the equation from used, I got a different answer. So there must be something wrong with my equation.
I've tried breaking it in to various parts as separate variables and calculating them, then using those variables in the overall equation, and that still didn't work and gave me an answer that was wrong in another way.
So I'm currently at a loss on how to fix it, starting to wonder if the way that vb handles long equations is different or something.
Any help is much appreciated.
You haven't given any sample data, so I can't verify that this gives the correct answer, but the last part of your equation is missing some parentheses.
Elevation = Math.Atan(((Velocity ^ 2) + Math.Sqrt((Velocity ^ 4) - (G * ((G * (Range ^ 2)) + (2 * DAlt * (Velocity ^ 2)))))) / (G * Range))
Note the parenthesis around the last G * Range.
Multiplication and division have equal precedence, so they are evaluated from left-to-right. See Operator Precedence in Visual Basic.
You were dividing everything by G, then multiplying the result by Range, whereas you needed to multiply G by Range, then divide everything by the result of that.
You can see the difference in this simple example:
Console.WriteLine(3 / 4 * 5) ' Prints 3.75
Console.WriteLine(3 / (4 * 5)) ' Prints 0.15
Out of curiosity I tried the problem. In order to have test data I found this web site, Range Tables For Mortars. I tested with the '82mm Mortar - Far' that has an initial velocity of 200 m/s. One problem I had, and don't know if I fixed it correctly, was that the first part of the equation was returning negative numbers... I also solved for the ±. To test I created a form with a button to perform the calculation, a textbox to enter the distance, and two labels to show the angles. This is what I came up with.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'A - launch angle
'Target
' r - range
' y - altitude
'g - gravity 9.80665 m/s^2
'v - launch speed e.g. 50 m/s
'
'
'Formula
'from - https://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_required_to_hit_coordinate_.28x.2Cy.29
'in parts
'parts - px
' p1 = sqrt( v^4 - g * (g * r^2 + 2 * y * v^2) )
' p2 = v^2 ± p1 note plus / minus
' p3 = p2 / g * r
'
' A = arctan(p3)
Dim Ap, Am, r, y As Double
Dim g As Double = 9.80665
Dim v As Double
Dim p1, p2p, p2m, p3p, p3m As Double
If Not Double.TryParse(TextBox1.Text, r) Then Exit Sub
y = 0
v = 200 '82mm Mortar - Far velocity
p1 = v ^ 4 - g * (g * r ^ 2 + 2 * y * v ^ 2)
If p1 < 0 Then
Debug.WriteLine(p1)
p1 = Math.Abs(p1) 'square root does not like negative numbers
End If
p1 = Math.Sqrt(p1)
'plus / minus
p2p = v ^ 2 + p1
p2m = v ^ 2 - p1
p3p = p2p / (g * r)
p3m = p2m / (g * r)
Const radiansToDegrees As Double = 180 / Math.PI
Ap = Math.Atan(p3p) * radiansToDegrees
Am = Math.Atan(p3m) * radiansToDegrees
Label1.Text = Ap.ToString("n3")
Label2.Text = Am.ToString("n3")
End Sub
Using the web site to verify the calculations the code seem correct.
Writing long formulas in a bunch of nested parentheses serves no purpose, unless you are going for confusion.

Find 3D point along the line at given distance

I have a problem and please let me know if my solution is correct.
I have a known point, at location A(x1,y1,z1) and the origin O(0,0,0) and I would like to find the coordinates of a point B(x2,y2,z2) that is located on the line OA, and the distance OB is 1.2 times greater then OA.
So, my idea is to obtain the equation of the line formed by points O and A.
The direction of OA is (-x1, -y1, -z1), so the equation of the line is:
x = -x1*t;
y = -y1*t;
z = -z1*t;
Distance OA is sqrt( (x1-0)^2 + (y1-0)^2 + (z1-0)^2). KNOWN
Distance OB is sqrt( (x2-0)^2 + (y2-0)^2 + (z2-0)^2). UNKNOWN
I can replace the x, y, z points determined for the line equation in the distance OB, and the result should be 1.2 times greater then the distance OA.
So, sqrt( (-x1*t-0)^2 + (-y1*t-0)^2 + (-z1*t-0)^2) = 1.2 * dist(OA).
I find t from here, solving the quadratic equation and I obtain the coordinates of the point by replacing the t in the equation of the line.
Is this correct?
Thank you for your time.
EDIT:
This is my code:
rangeRatio = 1.114;
norm = sqrt((P2(1) - P1(1))^2 + (P2(2) - P1(2))^2 + (P2(3) - P1(3))^2);
P3(1) = P1(1) + ((P2(1,1) - P1(1)) /norm) * rangeRatio;
P3(2) = P1(2) + ((P2(1,2) - P1(2)) /norm) * rangeRatio;
P3(3) = P1(3) + ((P2(1,3) - P1(3)) /norm) * rangeRatio;
I tried also norm = 1, and i get slightly different results but still not always colinear.
Thank you
It is even a lot easier; you can just multiply a, b and c by 1.2. This gives a line that is 1.2 times the size of the original line.