I have the following code for jumping of polygon:
def animate_up(canvas,id_rect,t,height_canvas,old_h_t=0):
if t<V_0/G: #jumping,max height
#t+=0.001
t+=(V_0/G)/20 #18=60*t-10*(0.5)*t^2 --> 36-120t+10t^2=0
t=float(Decimal(str(t)).quantize(Decimal('.01'), rounding=ROUND_UP))
new_h_t=V_0*t-G*(t**2)/2
diff_h_t=new_h_t-old_h_t #diff heights
canvas.move(id_rect,0,-diff_h_t)
#spin rect
if MODE=='SPIN': #spinning in the air
#if t>1.5:
#exit()
#else:
spin(canvas,id_rect)
root.after(15,lambda:animate_up(canvas,id_rect,t,height_canvas,new_h_t))
else: #calc time to fall down and activate fall down
t_to_fall=math.sqrt(old_h_t/(0.5*G))
animate_down(canvas,id_rect,0,height_canvas,t_to_fall)
def animate_down(canvas,id_rect,t,height_canvas,t_to_fall,old_h_t=0):
if t<t_to_fall: #falling
t+=(V_0/G)/20
t=float(Decimal(str(t)).quantize(Decimal('.01'), rounding=ROUND_UP))
new_h_t=G*(t**2)/2
h_t=new_h_t-old_h_t #diff heights
canvas.move(id_rect,0,h_t)
if MODE=='SPIN': #spinning in the air
spin(canvas,id_rect)
root.after(15,lambda:animate_down(canvas,id_rect,t,height_canvas,t_to_fall,new_h_t))
else:
#fix small spin(?) error after placing on platform
canvas.move(id_rect,0,467.5-canvas.coords(id_rect)[1])
let's say my parameters are:
G=15.0
V_0=35
MODE=='NORMAL' #the spin part is not relevant to the question in the momemt
With these parameters the jumping seems normal,but if I want a higher jumping,let's say V_0=80,then the polygon starting to lose some of it's upper part of the shape (pixels) when it is near the highest point of the jumping.
Same thing happening when the object fall and is near the bottom of the platform,it starting to lose it's lower parts of the shape (pixels).
explain of arguments:
canvas- Canvas object
id_rect- id (int) of the polygon object that is drawn in my canvas
t=time #start jumping/falling t=0
height_canvas= height of my canvas #relevant to other part of the code that not shown here
old_h_t=height after using the jumping/falling formula
pictures to illustrate:
Upper part of the pentagon is missing near highest point of jumping
Lower part of the pentagon is missing near platform after falling(maybe it's hard to see but the change is from bottom edge):
How to fix this problem?
In addition,the jumping is very elastic,it seems that the object is stretching while jumping/falling,is there a way to change that?(maybe that's because of the illusion of missing parts?)
Related
As you can see in the picture I inserted (from a game called Victoria 2), I want to create a bar in pygame to modify a variable (the number of pounds below the bar) depending on which part of the bar the gamer clicks (if they click on the left part of the bar, the red circle moves there and decrease the variable and if click on the right part, the circle moves there and increase the variable).
I tried:
if event.type==pygame.MOUSEBUTTONDOWN:
if mouse_rect.colliderect(bar_rect) and event.button==1:
circle_rect.x=mouse_rect.x
if circle_rect.x+mouse_rect.x:
budget=budget+1
if circle_rect.x-mouse_rect.x:
budget=budget-1
The circle moves, but the variable budget increases always, no matter if clicked on left or right, and it only increases one by one (because I don't know any other way to do it and what I want is a bigger or smaller increase depending on how far you click from the circle).
Any help?
Thanks!!!
Victoria 2 is a strategy game which allows you to balance the budget of your Goverment through a bar. Depending on where you clicked of the bar (left or right), the budget increases or decreases.
You need to look at how far along the slider you've clicked. Here's some untested code to show what I mean:
if event.type==pygame.MOUSEBUTTONDOWN:
if mouse_rect.colliderect(bar_rect) and event.button==1:
# move circle to clicked point
circle_rect.centerx=mouse_rect.x
# calculate distance from the slider origin
delta = circle_rect.centerx - bar_rect.left
# determine the percentage of the total budget
budget_pct = delta // (circle_rect.width)
# recalculate budget
budget = budget_pct * budget_max
Sorry if the title doesn't make it clear.
Here is the more detailed situation.
Given n dots and n rectangles.
Rectangles can overlap.
Dots are represented as (x,y)
Rectangles are represented as (x,y,w,h)
x,y refer to location in x and y axes, respectively
w,h refer to width and height, respectively
How do i check if the following two conditions are met simultaneously:
each dot falls in a certain rectangle (doesn't matter which)
AND
each rectangle contains at least one dot.
Is there a better way instead of iterating through each dot and each rectangle?
It would be best if you can show me how to do this in python.
Thanks!
I think you can use what is called oriented surfaces created by the mathematician Gauss i believe. this allows you to calculate any polygon area. Using the point to test as a fifth point and one other rectangle point as sixth point (duplicate) you can calculate a new area for this new six-side polygon. You will obtain the same area or a bigger area depending on the point position compared to the rectangle.
Addendum
The oriented surfaces allows you to calculate the area of any polygon when knowing their coordinates. The polygon must be defined as a set of points P(Xp,Yp) in the specific order describing the contour. Two consecutive points will be connected by a line.
In the picture below the polygon can be defined as the set [A,B,C,D], but also as [C,D,A,B] or [B,A,D,C].
It cannot be defined as [A,C,B,D] since this would define a polygon shaped like a butterfly wings as shown below.
Oriented Surfaces
For each couple of ordered successive point - meaning [A,B], [B,C], [C,D], [D,A] for the defined set [A,B,C,D] for example - the formula allows us to calculate the area of the triangle formed by a couple and the axis origin. This surface is oriented - meaning it has a positive or a negative value - according to the rotation (clockwise or counter-clockwise). In the figure below the triangles (OAB) and (OBC) and (ODA) will have a negative area, while the triangle (OCD) will have a positive area. By adding all those area, one can notice that the result will be the area of polygon (A,B,C,D), which is negative because it is drawn clockwise.
Calculations
You can find a clear example of the calculations and try a few things here: https://www.mathopenref.com/coordpolygonarea.html. To complete my example I have drawn a polygon similar (but not identical) to the ones above on this website and the result is as follow: -22
Adding a point
When you add a point, which is the point you want to test, you will obtain a 5-point polygon. The first thing you have to do is to place it in the correct order so that you don't have segments crossing. To do that you can create loop where the new point P is placed successively at the different positions in the set - meaning (PABCD), then (APBCD), etc until (ABCDP)- and calculate for each the area. The set giving you the maximum area in absolute value is the one you keep.
Here is an example from the website https://rechneronline.de/pi/simple-polygon.php. The first polygon is the initial, the second is badly defined and the last one is correctly defined.
One can see that that if the added point is outside the original polygon then the area is increased. At the opposite, if the added point is inside the original polygon, the area is decreased:
Note
If the original point set is not ordered correctly, you will have to reorder it as described just above
In Python you will have to use ordered object such as a list
To check that each rectangle has at least a point inside, you will have to check each point against all rectangles and maintain a dictionary describing which point is inside which rectangle
Adding: I also realized that since a rectangle is convex it is possible to know whether a point P is inside by just checking the four oriented triangle area in order namely (ABP) (BCP) (CDP) and (DAP). If those four area have the same sign then P is inside the rectangle (ABCD), otherwise it is outside.
I am doing a Vpython assignment for my physics 2 class, which is asking to program the electric field of a dipole. I have written the following code:
## constants
oofpez = 9e9 # stands for One Over Four Pi Epsilon-Zero
qe = 1.6e-19 # postive charge value
s = 4e-11 # charge separation
R = 3e-10 # display Enet on a circle of radius R
scalefactor = 3e-20 # for scaling arrows to represent electric field
## objects
## Represent the two charges of the dipole by red and blue spheres:
plus = sphere(pos=vector(s/2,0,0), radius=1e-11, color=color.red)
qplus = qe # charge of positive particle
neg = sphere(pos=vector(-s/2,0,0), radius=1e-11, color=color.blue)
qneg = -qplus # charge of negative particle
## calculations
## You will complete the lines required to make a loop calculate and display the net dipole electric field
## at equally spaced angles on a circle radius R around the dipole. The dipole is centered at the origin.
theta = 0
while theta < 2*pi:
rate(2) # tell computer to go through loop slowly
## Calculate observation location (tail of arrow) using current value of theta:
Earrow = arrow(pos=R*vector(cos(theta),sin(theta),0), axis=vector(1e-10,0,0), color=color.orange)
## assign the name TestLocation to be the observation location on the circle radius R
TestLocation=R*vector(cos(theta),sin(theta),0)
## write instructions below to tell the computer how to calculate the correct
## net electric field Enet at the observation location (the position of Earrow):
rPlus=TestLocation-plus.pos
rPlusMag=((R*cos(theta)-(s/2))^2+(R*sin(theta))^2)^0.5
rPlusHat=rPlus/rPlusMag
Eplus=oofpez*qplus/(rPlusMag)^2*rPlusHat
rNeg=TestLocation-neg.pos
rNegMag=((R*cos(theta)-(-s/2))^2+(R*sin(theta))^2)^0.5
rNegHat=rNeg/rNegMag
Eneg=oofpez*qneg/(rNegMag)^2*rNegHat
Etotal=Eplus+Eneg
Enet=arrow(pos=TestLocation,axis=Etotal*scalefactor, color=color.green)
## change the axis of Earrow to point in the direction of the electric field at that location
## and scale it so it looks reasonable
## Efield = arrow(pos=R*vector(cos(theta),sin(theta),0), axis=Etotal*scalefactor, color=color.blue)
Earrow.axis=Etotal*scalefactor
## Assign a new value to theta
theta = theta + pi/6
The assignment had a pre-made template created with the comments, the proper variables declared and said variables assigned the correct values, so in theory it should run correctly if I input the rest of the code correctly. The code I wrote starts at "rPlus=..." and ends at "Enet=..." However, when I run it (using GlowScript IDE) it gives an error message saying "Error: Property 'axis' must be a vector," which I'm sure means that there's something wrong with the value assigned to Enet.axis within that section of the code. I have looked through the code I've generated and can't seem to find the error.
We are learning python supplementary to our regular course work so I do not have any background in python besides these assignments. I don't need help with finding the electric field, just why the error message is popping up. Any help or hint in the right direction would be appreciated!
Thanks
On line 31 you used ^ instead of ** for exponentiation.
If you use the Chrome browser you can get the line number of an error.
I found the problem by inserting print statements at key locations in the code, which turned up the fact that rPlusMag was 0, not a vector.
I am trying to estimate the value of pi using a monte carlo simulation. I need to use two unit circles that are a user input distance from the origin. I understand how this problem works with a single circle, I just don't understand how I am meant to use two circles. Here is what I have got so far (this is the modified code I used for a previous problem the used one circle with radius 2.
import random
import math
import sys
def main():
numDarts=int(sys.argv[1])
distance=float(sys.argv[2])
print(montePi(numDarts,distance))
def montePi(numDarts,distance):
if distance>=1:
return(0)
inCircle=0
for I in range(numDarts):
x=(2*(random.random()))-2
y=random.random()
d=math.sqrt(x**2+y**2)
if d<=2 and d>=-2:
inCircle=inCircle+1
pi=inCircle/numDarts*4
return pi
main()
I need to change this code to work with 2 unit circles, but I do not understand how to use trigonometry to do this, or am I overthinking the problem? Either way help will be appreciated as I continue trying to figure this out.
What I do know is that I need to change the X coordinate, as well as the equation that determines "d" (d=math.sqrt(x*2+y*2)), im just not sure how.
These are my instructions-
Write a program called mcintersection.py that uses the Monte Carlo method to
estimate the area of this shape (and prints the result). Your program should take
two command-line parameters: distance and numDarts. The distance parameter
specifies how far away the circles are from the origin on the x-axis. So if distance
is 0, then both circles are centered on the origin, and completely overlap. If
distance is 0.5 then one circle is centered at (-0.5, 0) and the other at (0.5, 0). If
distance is 1 or greater, then the circles do not overlap at all! In that last case, your
program can simply output 0. The numDarts parameter should specify the number
of random points to pick in the Monte Carlo process.
In this case, the rectangle should be 2 units tall (with the top at y = 1 and the
bottom at y = -1). You could also safely make the rectangle 2 units wide, but this
will generally be much bigger than necessary. Instead, you should figure out
exactly how wide the shape is, based on the distance parameter. That way you can
use as skinny a rectangle as possible.
If I understand the problem correctly, you have two unit circles centered at (distance, 0) and (-distance, 0) (that is, one is slightly to the right of the origin and one is slightly to the left). You're trying to determine if a given point, (x, y) is within both circles.
The simplest approach might be to simply compute the distance between the point and the center of each of the circles. You've already done this in your previous code, just repeat the computation twice, once with the offset distance inverted, then use and to see if your point is in both circles.
But a more elegant solution would be to notice how your two circles intersect each other exactly on the y-axis. To the right of the axis, the left circle is completely contained within the right one. To the left of the y-axis, the right circle is entirely within the left circle. And since the shape is symmetrical, the two halves are of exactly equal size.
This means you can limit your darts to only hitting on one side of the axis, and then get away with just a single distance test:
def circle_intersection_area(num_darts, distance):
if distance >= 1:
return 0
in_circle = 0
width = 1-distance # this is enough to cover half of the target
for i in range(num_darts):
x = random.random()*width # random value from 0 to 1-distance
y = random.random()*2 - 1 # random value from -1 to 1
d = math.sqrt((x+distance)**2 + y**2) # distance from (-distance, 0)
if d <= 1:
in_circle += 1
sample_area = width * 2
target_area = sample_area * (in_circle / num_darts)
return target_area * 2 # double, since we were only testing half the target
I'm trying to solve the following problem:
Given an input of, say,
0000000000000000
0011111111110000
0011111111110000
0011111111110000
0000000000000000
0000000111111110
0000000111111110
0000000000000000
I need to find the width and height of all rectangles in the field. The input is actually a single column at a time (think like a scanner moves from left to right) and is continuous for the duration of the program (that is, the scanning column doesn't move, but the rectangles move over it).
In this example, I can 'wait for a rectangle to begin' (that is, watch for zeros changing to 1s) and then watch it end (ones back to zeros) and measure the piece in 'grid units'. This will work fine for the simple case outlined above, but will fail is the rectangle is tilted at an angle, for example:
0000000000000000
0000011000000000
0000111100000000
0001111111000000
0000111111100000
0000011111110000
0000000111100000
0000000011000000
I had originally thought that the following question would apply:
Dynamic programming - Largest square block
but now i'm not so sure.
I have little to no experience with regression or regression testing, but I think that I could represent this as an input of 8 variables.....
Well to be honest i'm not sure how I would do this at all. The sizes that this part of the code extracts need to be fitted against rectangles of known sizes (ie, from a database).
I initially thought I could feed the known data as training exercises and store the positive test results, but I'm really not sure where to go from here.
Thanks for any advice you might have.
Collect the transition points (from a 1 to a 0 or vice-versa) as you're scanning, then figure the length and width either directly from there, or from the convex hull of each object.
If rectangles can overlap, then you'll have bigger issues.
I'd take following steps:
get all columns together in a matrix (this is needed for proper filtering)
now apply a filter (need to google for it a bit) to sharpen edges and corners
create some structure to hold data for next steps (this can have many different solutions, choose your favorite and/or optimal)
scan vertically (column by column) and for each segment of consequent 'ones' found in a column (segment means you have found it's start end end y coordinates) do:
check that this segment overlaps some segment in the previous column
if it does not, consider this a new rect. Create a rect object and assign it's handle to the segment. for the new rect, update it's metrics (this operation takes just the segment's coordinates - x, ymin, ymax, and will be discussed later)
if it does, assume this is the same rect, take the rect's handle, assign this handle to the current segment then get the rect by it's handle and update it's metrics
That's pretty it. After this you will have a pool of rect objects each having four coordinates of its corners. Do some primitive math to approximate rect's width and height.
So where is the magic? Well, it all happens in the update rect metrics routine.
For each rect we have 13 metrics:
min X => ymin1, ymax1
max X => ymin2, ymax2
min Y => xmin1, xmax1
max Y => xmin2, xmax2
average vertical segment length
First of all we have to determine if this rect is properly aligned within our scan grid. To do this we compare values average vertical segment length and max Y - min Y. If they are the same (i'd choose a threshold around 97%, and then tune it for the best results), then we assume the following coordinates for our rect:
(min X, max Y)
(min X, min Y)
(max X, max Y)
(max X, min Y).
In other case out rect is rotated and in this case we take it's coordinates as follows:
(min X, (ymin1+ymax1)/2)
((xmin1+xmax1)/2, min Y)
(max X, (ymin2+ymax2)/2)
((xmin2+xmax2)/2, max Y)
I posed this question to a friend, and he suggested:
When seeing a 1 for the first time, store it as a new shape. Flood fill it to the right, and add those points to the same shape.
Any input pixel that is'nt in a shape now is a new shape. Do the same flood fill.
On the next input column, flood again from the original shape points. Add new pixels to the corresponding shape
If any flood fill does not add any new pixels for two consecutive columns, you have a completed shape. Move on, and try to determine it's dimensions
This then leaves us with getting the dimensions for a shape we isolated (like in example 2).
For this, we thought up:
If the number of leftmost pixels in the shape is below the average number of pixels per column, then the peice is probably rotated. Thus, find the corners by getting the outermost pixels. Use distance formula between all of them. Largest = hypotenuse, others = width or height.
Otherwise, this peice is probably perfectly aligned, so the corners are probably just the topleft most pixel, bottom right most pixel, etc
What do you all think?