I want to detect with what canvas object block. We have block, circle and triangle canvas objects.
I know there is if block in canvas.find_overlapping(x1,y1,x2,y2): method but doesn't shows with what object is block overlapping. It just shows if block is touching with any other canvas object.
overlapping_object=canvas.find_overlapping(block), overlapping_object could be a list that shows tags of objects that is block touching with.
How to make overlapping_object=canvas.find_overlapping(block) but it's correct. This one I typed here is just how could it look.
Thanks for any help!
I'm making 2D minecraft in tkinter and this is the thing that can really speed up my process.
If you're not willing to use other libraries and only tkinter, I don't think there's a built in function in tkinter that will allow it. I am also not sure why everything must be done in tkinter as it's not at all unusual for programs to use multiple libraries. Personally, given tikinter's limitations, I would use pygame to track polygons and their intersection but would never draw them. Short of using a third library (tikinter, python default, and other), there is one other approach. I mean it's really the only appraoch.
good ole fashioned math.
https://algs4.cs.princeton.edu/93intersection/
Here's some documentation on how to go about doing that. I wish you luck.
EDIT:
I think I accidentally found the answer to your question using math while studying for some other stuff. Still no way IN tkinter but here's a math explanation.
circle with center (x,y) and radius r
Polygon with z number of sides with x*2-1 number of points(x,y)
If you take iterate the lines of the polygon and put them through the following maths
Line J (x1,y1)(x2,y2)
m of Line J = (y1-y2)/(x1-x2)
create line P from circle center to P1 of LineJ
create line O from circle center to P2 of LineJ
Now we have a triangle
take the inverse cosine and length of P and O to get angle of the triangle you just made.
Make a right triangle by bisecting the triangle with line K starting at circle center and going out at the angle you just calculated.
Now you have line P and 1/2 angle of line P to line K
Now to find the intercept of that mid angle line
Tan(1/2 angle) = slope or m of the new line
using the x,y of the circle center calculate the slope intercept formula y=mx+b and get b
Now take the slope intercept formula for line J and set it equal to the slope intercept of the new line
line J (mx + b) = y = line P (mx + b)
Solve for y
Then plug y in the slope intercept for either and solve for x.
Once you've done this you have 4 points. The three points of the triangle, the point that makes a perpendicular line to center of circle from line J.
If any 3 of those points to the center of the circle in distance is smaller than r, they overlap. If they are are all > r then they don't overlap.
Related
I'm trying to create a traffic simulator using python (+ pygame and math libs).
I'm stuck at car movements, I've managed to create a fixed horizontal and vertical path using a list of coordinates, using nested for loops.
Now, since I'm in a crossroads I now have to make the 1/4 of a circle to make a left or right turn.
The car has to make a straight path for n pixels (and it's ok) then have to make the 1/4 following a circular path and then proceed towards a straight line again.
I have a list of coordinates, however, I don't know how to make it turn around the center of the circumference (which I know the coordinates of) while also turning the image relative to the center!
I'll give you an idea of the problem using an image
The red paths "1" are done, the problem is the blue tract "2", "O" coordinates are known, there are 4 "O" in total (one for each path).
I would suggest to use the equation of a circle which is (x – h)^2 + (y – k)^2 = r^2 where (h,k) are the coordinates of the cercle's center and r the radius.
The idea in your case could be to draw all discrete points (x,y) that verify this equation,
here is an example (for points where x and y are positive regarding the origin, if we follow your example):
import numpy as np
import matplotlib.pyplot as plt
center = (10,10)
radius = 5
th = 0.01
for x in np.arange(center[0],center[0]+radius+th, th):
for y in np.arange(center[1], center[1]+radius+th, th):
if abs((x-center[0])**2 + (y-center[1])**2 - radius**2) < th:
plt.scatter(x,y)
plt.show()
You can then control the number of points with the th, and even draw lines instead of just points to speed up the process
I am trying to perform a simple task using simple math in python and I suspect that the inherit error in converting from radians to degrees as a result of an error with floating point math (as garnered from another question on the topic please don't mark this as a duplicate question, it's not).
I am trying to extend a line by 500m. To do this I am taking the the endpoint coordinates from a supplied line and using the existing heading of said line to generate the coordinates of the point which is 500m in the same heading.
Heading is important in this case as it is the source of my error. Or so I suspect.
I use the following function to calculate the interior angle of my right angle triangle, built using the existing line, or in this case my hypotenuse:
def intangle(xypoints):
angle = []
for i in xypoints:
x1 = i[0][0]
x2 = i[1][0]
y1 = i[0][1]
y2 = i[1][1]
gradient = (x1 - x2)/(y1-y2)
radangle = math.atan(gradient)
angle.append((math.degrees(radangle)))
return angle
My input points are, for example:
(22732.23679147904, 6284399.7935522054)
(20848.591367954294, 6281677.926560438)
I know going into this that my angle is 35° as these coordinates are programmatically generated by a separate function and when plotted are out by around 3.75" for each KM. Another error as a result of converting radians to degrees but acceptable in its scope.
The error generated by the above function however, results in an angle that plots my new endpoint in such a place that the line is no longer perfectly straight when I connect the dots and I absolutely have to have a straight line.
How can I go about doing this differently to account for the floating point error? Is it even possible? If not, then what would be an acceptable method of extending my line by howevermany meters using euclidean geometry?
To add to this, I have already done all relevant geographic conversions and I am 100% sure that I am working on a 2D plane so the ellipsoid and such do not play a role in this at all.
Using angles is unnecessary, and there are problems in the way you do it. Using the atan will only give you angles between -pi/2 and pi/2, and you will get the same angle value for opposite directions.
You should rather use Thales:
import math
a = (22732.23679147904, 6284399.7935522054)
b = (20848.591367954294, 6281677.926560438)
def extend_line(a, b, length):
"""
Returns the coordinates of point C at length beyond B in the direction of A->B"""
ab = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
coeff = (ab + length)/ab
return (a[0] + coeff*(b[0]-a[0]), a[1] + coeff*(b[1]-a[1]) )
print(extend_line(a, b, 500))
# (20564.06031560228, 6281266.7792872535)
I am performing motion tracking of an object, and I am trying to identify the front and back of the object. The object is asymmetrical, which means that the centroid of the contour is closer to the front than the back. Using this information, I am approaching this as follows:
Draw contours of object
Find centroid
centroidx, centroidy = int(moments['m10']/moments['m00']), int(moments['m10']/moments['m00'])
Draw bounding ellipse
cv2.fitEllipse(contour)
Calculate major axis length as follows (and as shown in the figure)
MAx, MAy = int(0.5 * ellipseMajorAxisx*math.sin(ellipseAngle)), int(0.5 * ellipseMajorAxisy*math.cos(ellipseAngle))
Calculate beginning and ending x, y coordinates of the major axis
MAxtop, MAytop = int(ellipseCentrex + MAx), int(ellipseCentrey + MAy)
MAxbot, MAybot = int(ellipseCentrex - MAx), int(ellipseCentrey - MAy)
Identify which of the points is closer to the centroid of the contour
distancetop = math.sqrt((centroidx - MAxtop)**2 + (centroidy - MAytop)**2)
distancebot = math.sqrt((centroidx - MAxbot)**2 + (centroidy - MAybot)**2)
min(distancetop, distancebot)
The problem I am encountering is, while I get the "front" end of the ellipse correct most of the time, occasionally the point is a little bit away. As far as I have observed, this seems to be happening such that the x value is correct, but y value is different (in effect, I think this represents the major axis of an ellipse that is perpendicular to mine). I am not sure if this is an issue with opencv's calculation of angles or (more than likely) my calculations are incorrect. I do realize this is a complicated example, hope my figures help!
EDIT: When I get the wrong point, it is not from a perpendicular ellipse, but of a mirror image of my ellipse. And it happens with the x values too, not just y.
After following ssm's suggestion below, I am getting the desired point most of the time. The point still goes wrong occasionally, but "snaps back" into place soon after. For example, this is a few frames when this happens:
By the way, the above images are after "correcting" for angle by using this code:
if angle > 90:
angle = 180 - angle
If I do not do the correction, I get the wrong point at other times, as shown below for the same frames.
So it looks like I get it right for some angles with angle correction and the other angles without correction. How do I get all the right points in both conditions?
(White dot inside the ellipse is the centroid of the contour, whereas the dot on or outside the ellipse is the point I am getting)
I think your only problem is MAytop. You can consider doing the following:
if ycen<yc:
# switch MAytop and MAybot
temp = MAytop
MAytop = MAybot
MAybot = temp
You may have to do a similar check on the x - scale
So I have a random point on a canvas that will draw a line to a random point along a line across the bottom of the canvas. From that random point along the bottom of the canvas, I want to draw a line that diverges in the opposite direction (think of it like a " V ").
I'm having a serious issue conceptualizing what I need to do in order to accomplish getting the proper X coordinate for the second line that will be drawn (the Y-Coordinates will obviously be equal). I'm trying to do this using the addLine function in JES
If anyone could point me in the right direction I'd greatly appreciate it
It sounds like you basically want to just make an isosceles triangle here, so that the two legs of your V will be equal, though opposite in angle.
This doesn't define a strict angle between your two legs (which sounds like it's alright), but only that the x distance between both points and your point on the bottom of the canvas is equal.
Specifically, if you've got some code like this:
first_point = (a, b)
bottom_point = (c, d)
You want to make sure that the second_point is parallel though opposite to the first point, so the y coordinate should be the same, and the distance in the x-direction should be the same as the distance to the bottom_point, though in the opposite direction.
third_point_x = c - (a - c)
third_point = (third_point_x, b)
Hope that helps, let me know if you've got any more questions.
I have plotted n random points (the black points) and used delaunay triangulation, now I want to interpolate m random evaluation points (the red points) so I need to calculate which triangle the evaluation point is inside.
What is the approach for calculating the vertices of the triangle for each point?
For a given triangle, ABC, a point is inside the triangle if it is on the same side of line AB as point C is, on the same side of line BC as point A is, and on the same side of line AC as point B is. You can pre-optimize this check for each triangle and check them all until you find the triangle(s) it is in. See this page for more details.
To save computation, you can compute the minimum and maximum X and Y coordinates of the points for each triangle. If the X and Y coordinates of a point are not within the minimum and maximum values, you can immediately skip checking that triangle. The point cannot be inside it if it isn't inside the rectangle that bounds the triangle.
I'll assume that triangles do not intersect except of common edges.
You don't want to check every triangle (or subset of them) independently. The main reason is computation errors - due to them you may get answer "inside" for more than one triangle (or zero) which may break logic of your program.
More robust way is:
Find closest edge to the point
Select one of triangles touching this edge
Make one check for that triangle (the point lies on the same side as the third triangle vertex)
If "inside" - return this triangle
If "outside" - return another triangle on this edge (or "nothing" if there is no other triangle)
Even if you will return wrong triangle because of computation error, there still be exactly one triangle and point will lie close enough to it to accept such mistakes.
For #1 you can use something like quad-tree as Michael Wild suggests.
This simple example triangulates 10 random points, a further 3 random points are generated and if they fall inside a triangle the vertices are given:
import numpy as np
from pyhull.delaunay import DelaunayTri
def sign(a,b,c):
return (a[0]-c[0])*(b[1]-c[1])-(b[0]-c[0])*(a[1]-c[1])
def findfacet(p,simplice):
c,b,a = simplice.coords
b1 = sign(p,a,b) < 0.0
b2 = sign(p,b,c) < 0.0
b3 = sign(p,c,a) < 0.0
return b1 == b2 == b3
data = np.random.randn(10, 2)
dtri = DelaunayTri(data)
interpolate = np.random.randn(3, 2)
for point in interpolate:
for triangle in dtri.simplices:
if findfacet(point,triangle):
print "Point",point,"inside",triangle.coords
break
Using matplotlib to visualize (code omitted):
The dotted cyan lines now connect the points to interpolate with the vertices of triangle it lays within. The black lines are the convex hull, and the solid cyan lines are the delaunay triangulation.
A Delaunay triangulation is in itself a search data structure. Your Delaunay triangulation implementation probably has location functions. How have you computed the Delaunay triangulation of your points?
CGAL has an implementation of 2D and 3D triangulations. The resulting data structure is able to localize any point using a walk from a given point. See for example that chapter of the manual. CGAL is a C++ library, but it has python bindings.