I'm using Tkinter where an ASCII figure is printed on a label. I want it to change depending on where I click with the mouse, but I do not know how to tackle that problem. How would I map the mouse's coordinates so that it is restricted by a range, say [-n, n]? I am printing my mouse's (event.x, event.y) and I need those values restricted by the earlier stated interval. So instead of the values I get by moving my mouse ranging from 300 to 400, how can I map them to range from -15 to 15, for example?
Thank you in advance!
Edit: Here is what the program looks like - the center is the (0, 0) coordinate and I only want to be able to click on the sphere to rotate it. Therefore, I want to have my interval range from [-r, r] when clicking width the mouse.
Depends on your intervals. lets assume you have [-15,15], and mouse movement from 0-300, you map -15,15 onto [-150,150], which means that every spatial entity you move your mouse (1/150) is 15/150 = 0.1 step in the scale of your choice [-n,n], which you multiply with your mouse coordinate to get the corresponding value within your range [-n, n]. therefore its n*(n/m) with n being target interval and m being the coordinate interval. Why negative values? You must determine your [0,0] for your coordinate system, and this also depends on whether you want to increase size only or also shrink the figure. Maybe give some additional information or a code snippet!
Related
two scenarios
I have an x axis size, a y axis size, a render distance, a list of grid position numbers and a central grid position.
I am trying to create a list of all the grid positions within the render distance of a central grid position.
The size of the x and y axis may be different independently. Optimally this algorithm would not attempt to get positions where the render distance extends over the side of the x or y axis.
Thanks.
I'm writing this to help you answer your own question in the style that I would go about it. As with anything in coding, what you need to do is be able to break down a big problem into multiple smaller ones.
Design two functions to convert to and from (x, y) coordinates (optional, it'll make your life easier, but won't be as efficient, personally I would avoid this for a bit of a challenge).
Given n, size and distance, calculate up, down, left and right. If the size is different for different axis, then just provide the function with the correct one.
eg.
def right(n, size, distance):
return n + size * distance
def down(n, size, distance):
return n - distance
Given size, make sure the above functions don't go off the edge of the grid. Converting the points to (x, y) coordinates for this part may help.
Now you have the sides of the square, run the functions again to get the corners. For example, to get the top right corner, you could do right(up(*args)) or up(right(*args))
With the corners, you can now calculate what's in your square. Converting the points to (x, y) coordinates will make it easier.
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.
Question Explanation:
I have a fairly large file(up to 1 million lines) containing data from a mining machine. The data includes the X and Y coordinates of the machine. The machine should only be able to mine to the left (-X direction) or to the right (+X direction) and this occurs in a 'lane'. It should not be able to mine the same area again, but it can change Y-coordinates at any time(i.e, it can change lanes at any time) and skip certain areas. I want to determine in which direction the machine is moving at a given time. For example I want to see where the machine is moving to the left or to the right. Although this sounds simple enough, I am having a bit of trouble.
My attempt:
I am currently finding the sum of 100 values of the difference array of the X-coordinates (the difference array gives the distance the machine has moved). Ideally, if the X-coordinates are decreasing in a 100 point interval, then it should be moving to the left, and if the X-coordinates were increasing in that interval, it should be moving to the right. So if the sum was negative, it will append "0" to an array 100 times. I chose 100 because I thought it would be fairly accurate considering the high number of samples.
# miner_x = array of the x-coordinates of the machine
# miner_x_diff = numpy.diff(miner_x)
# 0 = Negative X direction
# 1 = Positive X direction
diffSample= [sum(miner_x_diff[i:i+100]) for i in range(0, len(miner_x_diff), 100)]
Direction = np.array([])
for value in diffSample:
if value < 0:
for _ in itertools.repeat(None, 100):
Direction = np.append(Direction,0)
else:
for _ in itertools.repeat(None, 100):
Direction = np.append(Direction,1)
# correct size
if Direction.size > miner_x.size:
Direction = Direction[0:Direction.size-(Direction.size-miner_x.size)]
The problem I am having is at the point it changes direction from left to right or vice versa, and this mostly occurs during a lane change. This if course expected, since the sum around that area could be close to 0. But I am not sure how to go about accounting for this change using my current method. Is there a more accurate way to determine the direction of the machine?
An example of a plot of the machines position using one particular data set is shown below (code omitted because it is unnecessary). The yellow points are positions where I had incorrect results occur .In this example there shouldn't be any yellow points. I have not shown the direction color in this example but you can of course see it if I say the start position is at the bottom right.
I will appreciate any help/advice/hints :)
Edit:
Here is a picture of what I want (mind the Paint skills). Note that I don't want to 'see' a straight line, just to know that it is moving in those directions at those points. Green is the start point.
Start by using a smaller sample window. How much time is represented by 100 sample points? The interval should be small enough that you can simply look at the displacement between the initial and final position and have a direction for that time segment. (You do realize that summing the difference of consecutive pairs of numbers is the same as subtracting the first from the last number, don't you?) If you catch the machine at a point where it's turning around, you may get indeterminate data but the samples before and after will show a straight vector.
I am creating bunch of different SVG files in Python using svgwrite module. I need to present those pictures later on a website.
Since those pictures consists of different mathematical object I am working in whole plane, both with positive and negative numbers. That means that I need to shift all the objects so they will be visible and maintain the structure. Sometimes shifting those objects is not hard, but since I have to do it in almost all my work I am looking for something more general.
So I am looking for something that will shift all of the objects and maintain their structure, so that everything will be visible and the size of the picture would be minimal(meaning the width/height).
I search the official documentation but haven't been successful so far, maybe just blind.
Update To make it clearer I have added an example
Python example:
import svgwrite
im = svgwrite.drawing.Drawing()
im.add(im.line( start = (-10,-10),\
end = (20,20),\
stroke= 'black'))
im.saveas('example.svg')
Then, when I view example.svg in e.g. Firefox there would be only part the "positive" part that is line from [0,0] to [20,20].
Or slightly different example:
import svgwrite
im = svgwrite.drawing.Drawing()
im.add(im.line( start = (10,10),\
end = (20,20),\
stroke= 'black'))
im.saveas('example2.svg')
Now there is unnecessary gap between [0,0] and the line, which starts at [10,10].
So, to sum it up. Imagine bunch of SVG objects, they can be drawn anywhere. I want to find minimal x_min, y_min coordinates throughout all the objects and then:
if the the coordinate x_min (resp. y_min) is negative, add |x_min| (resp. |y_min|) to all the x (resp. y) coordinates of all objects. Where |a| stands for absolute value of a
if the the coordinate x_min (resp. y_min) is positive, substract x_min (resp. y_min) from all the x (resp. y) coordinates of all objects
After that the all the objects will be visible, and they will touch one or both axis at zero. As discussed below, same result might be achieved by shifting the origin (in corresponding way).
Note While I am at it, the similar problem comes with module Image.
Assuming you want to shift the origin, what you need to do is surround your graph lines with a group element and apply a transform to that.
I don't know the proper syntax for that library, but going by the documentation, it will be something like the following:
im = svgwrite.drawing.Drawing()
g = svgwrite.container.Group(transform='translate(50,50)')
im.add(g)
g.add(im.line( start = (-10,-10),\
end = (20,20),\
stroke= 'black'))
im.saveas('example.svg')
If I understand your clarifications right, what you want is for the diagram not to go off the page when rendered (?). If that's the case, what you need to do is add a viewBox to your SVG.
First, keep track of the minimum and maximum, x and y values over the whole diagram. You may have to do that yourself, or it is possible the svgwrite library will do that for you.
Once the diagram is finished, add a viewBox attribute to your root SVG element that contains these values.
The viewBox takes this form:
minX minY width height
where minX minY is the top left of the diagram. So, for your first example above, the viewBox would be:
<svg viewBox="-10 -10 30 30" ... >
and for your second example it would be:
<svg viewBox="10 10 10 10" ... >
Then when the picture is rendered in, say, a browser, it will use the picture dimensions given by the viewBox attribute to position and scale the contents to fill the container (the browser window, <div> etc).
If, rather than having it fill the container, you want to specify a default width and height for the diagram (eg. 200px x 200px), add width and height attributes to the SVG. Like this:
<svg width="200px" height="200px" viewBox="-10 -10 30 30">
<line x1="-10" y1="-10" x2="20" y2="20" stroke="black" />
</svg>
Demo here
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?