If I have line like this (a xy plot in the future)
`Canvas {
id:canvas
onPaint:{
var ctx = canvas.getContext('2d');
ctx.moveTo(0,0);
ctx.lineTo(50,20);
ctx.lineTo(50,70);
// etc...
}
}`
so, is there a good way to check mouse press event on this line? i.e. If I have a plot and want to show context menu on right click on graph line
Unfortunately, AFAIK, you should keep track of what you draw. Canvas doesn't store drawn stuff as vector graphics(again, AFAIK), but on a raster, so there's no way to get it to tell you where the lines/points are.
You could push each point you pass to ctx.moveTo and ctx.lineTo to a list or other structure. Then, on click, iterate over all line segments (designated by pairs of points you stored) and check if distance of the clicked point to the line segment is within some selection tolerance distance you want.
To check the distance, you can use this:
Shortest distance between a point and a line segment
I don't know if this is the simplest way, but it works.
Related
Iam nooby in godot, I have to use A* to traslate the player to the goal position, but I do not know how to start, pls help!! basically I have just 2 tiles in the tilemap, 1 of them is allowed to pass over it, I have to extract I guess the allowed tile and calculate the distance between the position player with the position goal, getting the real distance and then check cell per cell which has the lowest cost, but I do not know how to do that :c
func get_player_init_pos():
var pos = map_to_world(Vector2(54,1))pos.y += half_cell_size.y
return pos
func is_tile_vacant(pos, direction):
var curr_tile = world_to_map(pos)
var next_tile = get_cellv(curr_tile + direction)
var next_tile_pos = Vector2()
if(next_tile == 0):
next_tile_pos = map_to_world(curr_tile + direction)
else:next_tile_pos = pos
return next_tile_pos
I have this, the first part of the code is to locate the player in the map and the second is for check the tile walls in the map
You could roll your own path finding algorithm. However, there is little point in doing so, since Godot has a AStar class you can use. However, you probably don't need to use that either, because Godot has a navigation system. And that is what I'm going to suggest you to use.
First of all, you can specify both navigation and collision polygons on your tiles. You need to have the navigation polygons. Go ahead and do them.
Second you want to have a Navigation2D in the scene tree and have your TileMap as a child.
And third, you can ask the Navigation2D for a path with get_simple_path, you pass the start and end positions as arguments and you get an array of points that make up the path.
Since you mention A*, I'll briefly explain using the AStar too anyway.
First, you need to add the cells with add_point. It requires ids. It is a good idea to be clever with the ids so you can compute the id for a given position. For example x * width + y if you know the size.
So you can iterate over the tiles in your TileMap and call add_point for each one (You don't need to add cell that are not passable).
Then you need to specify the connections with connect_points (it takes the ids of the points as parameters).
And finally you can call get_point_path passing the start and end ids. Again it gives you a array of points.
I am using fabric.js for creating a canvas project. I have created a line using the framework. However, is there a way to set a fixed length on the line. Reason being, the line is draggable and it stretches.
line = makeLine([ 250, 125, 250, 175 ]),
It got quite complicated in the comments so let's sum up few things:
Here's a solution for the simple case:
In your http://jsfiddle.net/sprakashg/rbhhP/ you have few lines like this:
var p = e.target;
p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
Here, the line1 is your Line and p is your Circle.
You can compute the initial length of the line and store it. Next, you can compute a current line direction, which is from line.p1 to position of p. Now, if you normalize this direction and multiply by the initial line length you'll get the new direction, pointing at your circle, but keeping initial line length. Add it to your line start and you can store this value in p.line1.set().
This will work if you have two circles connected with a line, but if you have few lines connected to the single circle, then you'll not be able to move it.
Solution for more complex case:
In your Stickman case you can't move a knee because there's only one another point that satisfies your lines length constraints. In such case I'd add a simple hierarchy to the model.
If you assume some Circle to be the root of the model, then all other objects are leaves and branches of some model tree. Now, when you move some circle, you should do the computations mentioned above just for the line, that connects it with the parent.
Then you can take all the circles below in your model hierarchy and move them by the same amount that you moved your main Circle.
With this approach, when you try to move a knee then your pelvis-knee line will move with your mouse but keep its length (as you want to). But during the movement of the knee the rest of a leg will move by the same amount, so in effect you'll also keep the length of a knee-ankle line.
I have tried to add a click handler to the map, but am not sure how to tell when the polygon has finished drawing.
Is there a simple function to get the polygon coordinates on draw end ?
You can probably adapt https://stackoverflow.com/a/24835176/228885 for your purposes. As mentioned in another answer feature.once('change', ...) might be another way to go. I expect in that case you would pick the last element from the feature passed to the handler. Then you would extract the coordinates out of it and off you go.
TLDR; Listen add or change of features, extract coordinate.
I am trying to write an application to draw schematic diagrams which contain rectangles, lines and circles. Now I want to add another functionality to drag a rectangle to different position. The problem I am facing is to detect whether I have clicked within a rectangle or not. I know there is a function like Rectangle.Contains(Point). To use such method I need to use a for loop to check against each rectangle. If I have a large number of rectangles present, then its not wise to use this method. Is there any other way to do this task.
You need a computer graphics textbook, this and similar problems are often discussed.
If memory serves me, make sure the point is below the top edge of the rectangle, above the bottom edge, left of the right edge and right of the left edge.
Regarding testing a bunch of rectangles in a loop. Consider having a circle that each rectangle fits in, a bounding circle. First test to see if the point is farther from the origin of the circle than the radius of the circle. If so there is no need to test the rectangle, its a miss. OK, that was a very theoretical answer. In reality calculating the distance from the point to the origin can be a very expensive calculation, it involves a square root, it may be faster to do the four comparisons of the point in rectangle check. Again if memory servers me, we don't really care what the distance from the origin is only if it is greater than the radius. So only partially perform the distance calculation, omitting the final square root, and compare against the square of the radius. Of course you still need to experiment and profile to make sure this bounding circle check is faster than just doing the regular point in rectangle check and you need to make sure you will have sufficient misses to offset the hits where you will end up doing both the bounding circle and rectangle checks.
You need to use a spatial index to find quickly in which rectangle the mouse is. I suggest a R-tree, here is the theorical part:
http://en.wikipedia.org/wiki/R-tree
And the c#,implementation:
http://sourceforge.net/projects/cspatialindexrt/
Create an rtee, add your rectangles then call the rtree.nearest method with the mouse coordinate to know the rectangles containing the mouse cursor. You can play with the distance parameter.
Hope it helps,
Anben Panglose.
I would go about dividing the display region into a quadrant.
Then place the rectangles into top-left, top-right, bottom-left, bottom-right grids.
Placing them means, creating a list for every quadrant and placing the rectangles in it.
Once the point is clicked, determine which quarter it belongs to and search in those rectangles only. This approach reduces your linear search by 4 times.
Remember that you need to also take care of overlapping where the point can belong to many rectangles. Here the z-order of your rectangles matter. So while the list is maintained for a quadrant, it should be sorted with it's z-order as a key.
Hope this helps.
May be something like this?
public bool isRectangelContainPoint(RectangleF rec, PointF pt)
{
if (pt.X >= rec.Left && pt.X <= rec.Right && pt.Y <= rec.Bottom && pt.Y >= rec.Top)
return true;
else
return false;
}
App works this way:
User enters a starting location and a distance. User can choose to draw circles, or lines over the roads. Circles work fine. Lines used to work.
When Lines, the code finds the lat/long of the starting location, then for the points N, S, E, W of the origin at the distance set by the user (say, 100km). Starting with the N destination, the code calls google.maps.DirectionsService() to get directions from the origin to N. This returns an array of lat/longs in the the route.overview_path.
NOTE: I COULD use the directionsRenderer() to draw the route, BUT, the distance drawn would be greater than the distance set by the user. Drawing the entire route from the origin to the point N might be 124km over the roads, and I just want to draw 100km.
Instead, I step through the route.overview_path[] array, checking the distance between that point and the point of origin, adding each point to a new array. When the distance is greater than the dist set by the user, I stop, pop off the last element, then create a new Polyline based on this 2nd, smaller array.
I've spent the entire day in Chrome's developer mode walking through the javascript, setting breakpoints, watching locals, etc. The array of points passed in google.maps.Polyline({}) is a good array of unique points. I just cannot figure out why they aren't rendering.
Ultimately, the code used to draw 4 lines starting at the point of origin, one heading North, one heading East, South, West. etc....
The code is here: http://whosquick.com/RunViz.html
Thank you for your attention.
Nevermind. Solved it.
var objGeo = new LatLon(Geo.parseDMS(myroute.overview_path[0].Pa), Geo.parseDMS(myroute.overview_path[0].Qa));
I had inadvertently switched Pa with Qa.