Animating With Gloss in Haskell - animation

Here's my code for a little pattern that looks something like this. (Not the most efficient code I know). Now, I want to make stars rotate using animate. but I'm not sure how to use display and animate together in one program. Any help would be appreciated. Thanks.
import Graphics.Gloss
main = display (InWindow "Gloss" (700,700) (0,0))
black (picture 100)
picture :: Float -> Picture
picture 0 = text "Value cannot be 0"
picture number = scale 6.5 6.5 (color rose $ drawpicture number)
orangered, orangered2, orangered3 :: Color
orangered = makeColor 1.0 0.251 0.0 0.7
orangered2 = makeColor 1.0 0.251 0.0 0.5
orangered3 = makeColor 1.0 0.251 0.0 0.3
intervalsmall = [0,11.25,22.5,33.75,45,56.25,67.5,78.75]
intervalbig = [0,22.5,45,67.5,90,112.5,135,157.5,180,202.5,225,247.5,270,292.5,315,337.5]
xlist = [2,4..50]
ylist = [0,2..48]
squares = pictures[rotate x (line [(-50,0),(0,50),(50,0),(0,-50),(-50,0)]) | x <- intervalsmall]
stars = pictures[rotate x ((pictures [line [(-8.5,0),(0,50),(8.5,0)],line[(0,50),(0,0)]])) | x <- intervalbig]
grid = pictures[line [(0,y),(x,50)] | x <- xlist, y <- ylist, x-y==2]
insidegrid = pictures[
translate 0 (-50) grid,
rotate 90 (translate 0 (-50) grid),
rotate 180 (translate 0 (-50) grid),
rotate 270 (translate 0 (-50) grid)]
drawpicture :: Float -> Picture
drawpicture number = pictures [
color red (pictures [circle 50,circle 8.5]),
line [(-50,-50),(-50,50),(50,50),(50,-50),(-50,-50)],
squares,
scale 0.7 0.7 squares,
scale 0.49 0.49 squares,
scale 0.347 0.347 squares,
scale 0.242 0.242 squares,
color orange stars,
color orange (scale 0.178 0.178 stars),
rotate 11.25 (scale 0.178 0.178 stars),
translate (-50) 0 grid,
rotate 90 (Translate (-50) 0 grid),
rotate 180 (Translate (-50) 0 grid),
rotate 270 (Translate (-50) 0 grid),
color orangered insidegrid,
color orangered2 (rotate 45 insidegrid),
color orangered3 (rotate 22.5 insidegrid),
color orangered3 (rotate 67.5 insidegrid)
]

It's easier if you have separate draw functions for each visual element, but the basic answer is: to animate it just use the animate function and rotate the image components you desire to "move":
import Graphics.Gloss
main = animate (InWindow "Gloss" (700,700) (0,0))
black picture
picture :: Float -> Picture
picture 0 = text "Value cannot be 0"
picture number = scale 6.5 6.5 (color rose $ drawpicture number)
orangered, orangered2, orangered3 :: Color
orangered = makeColor 1.0 0.251 0.0 0.7
orangered2 = makeColor 1.0 0.251 0.0 0.5
orangered3 = makeColor 1.0 0.251 0.0 0.3
intervalsmall = [0,11.25,22.5,33.75,45,56.25,67.5,78.75]
intervalbig = [0,22.5,45,67.5,90,112.5,135,157.5,180,202.5,225,247.5,270,292.5,315,337.5]
xlist = [2,4..50]
ylist = [0,2..48]
squares = pictures[rotate x (line [(-50,0),(0,50),(50,0),(0,-50),(-50,0)]) | x <- intervalsmall]
stars = pictures[rotate x ((pictures [line [(-8.5,0),(0,50),(8.5,0)],line[(0,50),(0,0)]])) | x <- intervalbig]
grid = pictures[line [(0,y),(x,50)] | x <- xlist, y <- ylist, x-y==2]
insidegrid = pictures[
translate 0 (-50) grid,
rotate 90 (translate 0 (-50) grid),
rotate 180 (translate 0 (-50) grid),
rotate 270 (translate 0 (-50) grid)]
rotVal :: Float -> Float
rotVal x = x - (x / (2*pi))
drawpicture :: Float -> Picture
drawpicture number = pictures [
rot $ color red (pictures [circle 50,circle 8.5]),
line [(-50,-50),(-50,50),(50,50),(50,-50),(-50,-50)],
rot $ squares,
rot $ scale 0.7 0.7 squares,
rot $ scale 0.49 0.49 squares,
rot $ scale 0.347 0.347 squares,
rot $ scale 0.242 0.242 squares,
rot $ color orange stars,
rot (color orange (scale 0.178 0.178 stars)),
rot (rotate 11.25 (scale 0.178 0.178 stars)),
translate (-50) 0 grid,
rotate 90 (Translate (-50) 0 grid),
rotate 180 (Translate (-50) 0 grid),
rotate 270 (Translate (-50) 0 grid),
rot $ color orangered insidegrid,
rot $ color orangered2 (rotate 45 insidegrid),
rot $ color orangered3 (rotate 22.5 insidegrid),
rot $ color orangered3 (rotate 67.5 insidegrid)
]
where rot = rotate (rotVal number)

It is too much to write out all for you but you just have to add another argument to your picture function that is a Float and represents time. So display would be replaced by animate. So.
main = animate (InWindow "Gloss" (700,700) (0,0))
black (picture 100)
picture :: Float -> Float -> Picture
picture number time = -- whatever you have to do
You'll have to change your helping drawing functions to take this time param. Let's say you want to rotate the whole think once ever 5 seconds you can just multiply this time coming in and get an angle angle = time*(pi*2/5) then you can use this angle for trig functions to calculate new x and y positions from the center.

Related

Fisheye camera calibration, when the Angle of incidence is greater than 75 degrees, the calculated pixel coordinates are out of the picture

The fisheye calibration results as follow:
DIM=(570, 570)
K=np.array([[266.36324787557334, 0.0, 286.1343601122261], [0.0, 265.62825365308095, 278.7737221129092], [0.0, 0.0, 1.0]])
D=np.array([[-0.0759953338456378], [0.021844363556585086], [-0.0788346808974877], [0.03431624249604429]])
The projection method is given in opencv org:
https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html
def get_pixel_location(ele,azi,isDeg=True):
print("ele azi:",ele,azi)
if(isDeg):
ele,azi=ele*deg2rad,azi*deg2rad
# print()
xc,yc,zc=np.cos(ele)*np.sin(azi),np.cos(ele)*np.cos(azi),np.sin(ele)
print("xc yc zc:",ele,azi)
a=xc/zc
b=yc/zc
r=np.sqrt(a*a+b*b)
import math
theta=math.atan(r)
theta_d=theta*(1+D[0]*theta**2+D[1]*theta**4+D[2]*theta**6+D[3]*theta**8)
x_=theta_d[0]/r*a
y_=theta_d[0]/r*b
res=np.matmul(K,np.array([x_,y_,1]).T)
return res[0],res[1]
I calculate its corresponding pixel coordinates based on the incidence Angle and azimuth Angle, and when the incidence Angle is greater than 75 degrees, the calculation results are out of my image range
azi=90
eles=range(5,30,5)
for ele in eles:
pix_x1,pix_y1=get_pixel_location(ele,azi)
print("像素坐标:",pix_x1,pix_y1)
output:
ele azi: 5 90
xc yc zc: 0.08726646259971647 1.5707963267948966
像素坐标: 643.0703082567584 278.7737221129092
ele azi: 10 90
xc yc zc: 0.17453292519943295 1.5707963267948966
像素坐标: 600.9383069020462 278.7737221129092
ele azi: 15 90
xc yc zc: 0.2617993877991494 1.5707963267948966
像素坐标: 576.6204832801376 278.7737221129092
ele azi: 20 90
xc yc zc: 0.3490658503988659 1.5707963267948966
像素坐标: 560.5995805890057 278.7737221129092
ele azi: 25 90
xc yc zc: 0.4363323129985824 1.5707963267948966
像素坐标: 547.3589855919477 278.7737221129092

matlab plot data over an image

I would like to plot a scatter plot over a background image. But the origin of the image is at the top left corner. I need the bottom left of the image to be the origin so the bottom left = (0, 0.75) and top right (14, 1.25)
So I need to scale the image to my data from pH 0 - 14 (This is the x axis) and Eh 0.75 - 1.25 (This is the y axis)
Eh = [327.06 561.34 506.82 602.58 745.02 745.04 ...
693.96 682.9 648.46 468 412.18 522.94 459.74]./1e3; % V
pH = [6.4 4.51 5.08 4.98 3.63 4.31 6.24 6.22 4.94 6.44 7.05 5.09 4.63]; %pH
I=imread('Fe_Pourbaix.png');
xImg = linspace(0, 14, size(I, 2));
yImg = linspace(-0.75, 1.25, size(I, 1));
image(xImg, yImg, I, 'CDataMapping', 'scale');
hold on;
plot(pH, Eh,'*','LineWidth',2);
grid on;
Suppose I Need to flip the data? The below image is what I need is the x and y I need to produce to overlay my data

How to proportionally elongate image down center of camera

So I currently have a screen with a width of 1080 pixels. I also have a camera, centered in the middle of the screen. The camera gives me the position on a screen as a value between 0 and 1. This way, when the width of the screen is multiplied by the position, you get its placement in the screen window. See below:
so the old is
0 , .5, 1 <-- The position in the screen (X)
0, 540, 1080 <-- The screen size (Y)
X*Y = Pixel Placement
However, I would like to crop off some of the camera so it corresponds more accurately to my screen. The new is:
.25, .5, .75 <-- (X)
0, 540, 1080 <-- (Y)
What is the equation for calculating this placement? I feel like I've learned this but forgotten the method. Thanks.
You have linear relationship
Y = Yleft + (X - Xleft) * (Yright - Yleft) / (Xright - Xleft)
For your example values
Yleft = 0
Yright = 1080
Xleft = 0.25
Xright = 0.75
so
Y = (X - 0.25) * 1080 / 0.5 = 2160 * (X - 0.25)
for X = 0.5
Y = 2160 * (0.5-0.25) = 540

Calculating a location on a circle given an angle of rotation

Okay algebra and trig are not my strong suit by any means so here is what I need to do.
I have a circle which is measured in degrees from +180 to -180 (360 total)
Given the center point of the circle stays the same, Cx , Cy.
The angle varies from -180 to +180
I need to locate a point that regardless the given angle is + 3 units away that is at the 90 degree position and the 270 degree position (from the given degrees)
So like...
Angle = 0
Point 1 -> x = 0, y -3
Point 2 -> x = 0, y + 3
And if the angle was say 90 (provided its measured Clockwise)
Point 1 -> x = -3, y = 0
Point 2 -> x = 3, y = 0
What I need is a forumla that will accept Angle, then tell me what my x/y should be 3 units away from the origin.
I have tried: EDIT Updated to double precision using Java.
`double x = Cx + 3 * Math.cos((d + 90) * Math.PI / 180);'
'double y = Cy + 3 * Math.sin((d + 90) * Math.PI / 180);`
this gives me mixed results, I mean sometimes it's where I think it should be and other times its quite wrong.
Assuming Cx = 0.500, Cy = 0.500
Sample Data: Result:
Deg = 0 x = 2 / y = 5
Deg = 90 x = -1 / y = 2
Deg = 125 x = -0.457 / y = 0.297
Deg = 159 x = 0.924 / y = -0.800
I realize I am only calculating one point at this point but do you have any suggestions on how to get the first point working? at say 90 degrees from whatever degree I start with?
x = Cx + r * Math.cos( (d+90) * Math.PI / 180 );
y = Cy + r * Math.sin( (d+90) * Math.PI / 180 );
Seems that this is the correct formula for what I was trying to accomplish. This will take any value for Cx/Cy's origin add the Radius r, then calculate the degrees + 90 and convert to radians.. Once all that magic takes place, you're left with an x/y coord that is 90 degrees of where you started.

Mask overlay with matlab

I have the following code which shows an image called zero.
I would like just to overlay a mask image (only 0 and 1 values) of the same dimensions so that 0 values are transparent (and then we can see the values of the zero image) and 1 values are shown in black.
What could I do?
hFig = figure(1);
set(hFig, 'Position', [11 11 27 7.5]);
set( gca, 'Units', 'normalized', 'Position', [0.05 0.05 0.93 1.2] );
set(0,'defaultFigureUnits','centimeters');
m_proj('equidistant cylindrical','longitudes',[-15 21],'latitudes',[11.5 18]);
m_gridF('ytick',4,'tickdir','out','ticklen',0.005,'linestyle','none');
hold; Plat=18-[0:13]*0.5;
Plon=-15+[0:72]*0.5;
[Plg,Plt]=meshgrid(Plon,Plat);
m_pcolor(Plg,Plt,zero);shading flat;
hold on;
polarmap(flipud(polarmap),0)
M=m_shaperead('clip');
for k=1:length(M.ncst),
m_line(M.ncst{k}(:,1),M.ncst{k}(:,2),'color','k');
end
hold;
h=colorbar('SouthOutside');
set(h, 'Position', [0.13 .1 .78 .05]);
set(get(h,'title'),'string','test','fontsize',14)
hold;

Resources