Snaping circle to rectangle/line - c#

I am trying to implement some kind of snapping functionality in WPF for a circle (which represents my mouse) and it should snap to another object (normally this would be a line or a rectangle).
Is there a way to do this kind of functionality with WPF without doing all the calculations on my own and if not is there an easy way (library?) to get this kind of information?
Edit: I want to snap the border of the circle to the border of the rectangle/line.

As a first step, you should find the point on the rectangle that is the closest to the cursor, and the distance between the two: extending the edges of the rectangle, you partition the plane into 9 regions. Depending on the region where the cursor lies, the searched distance will be the distance to a corner (Euclidean distance formula) or the distance to an edge (difference of abscissas or ordinates).
Subtract the circle radius from this distance. This will tell you if you are close enough for a snap.
When a snap is possible, move the cursor along the line from the current cursor position to the closest point until you hit the corner or edge. You will need to use the parametric equation of the line segment.
The complete discussion requires some care but only involves simple math.
A similar approach is possible to snap to a line segment. Here is a trick: if you rotate the line segment to make it horizontal, you can consider the line segment as a degenerate rectangle and use the same snapping algorithm. Rotate the line segment and the cursor, apply the snapping logics and then counter-rotate the updated cursor.

That kind of functionality only takes a few lines of code to replicate... I doubt that you'll find a 'library' of code to do it for you. The method is as follows:
Keep a collection that contains the 4 Points that form each shape's bounding box. You then need to handle to MouseMove event on the Canvas, or shape container. In this event, you simply need to ascertain whether the current mouse position is within a certain distance from any of the shape edges... you'll have a little bit more work to do with non-rectangular shapes to calculate their edges, but the principal is the same.
If you detect the presence of a nearby shape, then you simply need to change the value of the nearest dimension to that of the nearby shape... the snap. That's it... much easier than you think.

Related

How to animate a simple 3D shape using Helix Toolkit?

I'm trying to animate a simple rectangular shape so that it scales in size in a certain direction. As it is, I am making a rectangle that extends from point A to B. The end goal is to animate it so that it starts at A and is transformed to be the length required to get to B.
I'm pretty new to animation in general, so this process seems finicky to me.
Right now I am:
Creating a vector between the start and end point
Finding the 8 corners of the rectangle along that vector
Creating 2 triangles for each face of the rectangle
Rendering the shape
This is all being done by using a MeshBuilder object and adding the triangles and points individually.
So, the way I'm creating the prism doesn't really help for what I need to do. Ideally I suppose, I would just create a short prism aligned between the points, and then just extend the rectangle to be the right length in an animation.
Any thoughts?
I solved this is a sense by scaling the 3D object from a size of 0 in the X/Y/Z to 1.0. So instead of the prism "extending" from A to B, it more or less "grows" to B.
Note that the ScaleTransform3D needed to have the CenterXYZ properties set to the coordinates of point A in order for it to be anchored to the correct position.
If I find a better solution, I'll update this answer later.

Detect mouseover of non-square part of an Image

So I am working on a Risk type game in XNA/C#. I have a map, similar this one, and I need to be able to detect mouseovers on each territory (number). If these areas were squares, it would be easy, as they could each be represented by a rectangle. However, they are different size polygons. Is there a polygon shape that behaves similar to a square? If there isn't, how would I go about doing this?
I sugest this:attach color to each number, recreate your picture in these colors: every shape will be in its particular color. Dont draw it onscreen, use it only as reference map. And when the user clicks or moves mouse over your original map, you just simply project mouse coordinates into the color map, check the color of pixel laying under the mouse and because you have each color associated to number of territory...
This is not c# specific (as I've never written anything in the language, so no idea of what apis there are), though there are 2 algorithms that come to mind for detecting if a point is inside a polygon (which can be used to detect if a mouse point is over another polygon/map shape).
One is based on raycasting, where you cast a ray in 1 direction from the (mouse) point to "infinity" (edge of the board in this case) and count the number of times it crosses the polygon's edges. If it is odd, then the point is inside the polygon, if it is even, then the point is outside of the polygon.
A wiki link to it: http://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
The other algorithm that comes to mind works only for triangles I think but it can be more simple to implement I think (taking a quick glance at your shapes, I think they can easily be broken down into triangles and some are already triangles). It is to do with checking if the point is on the same (internal) "side" of all the edges in the triangle. To find out what "side" a point is on vs an edge, you'd take create 2 vectors, the first vector would be the edge itself (made up of 2 points) and the other vector would be the first point of that edge to the input point, then calculate the cross product of those 2 vectors. The result will be negative or positive, which can be used to determine the "direction".
A link to it: http://www.blackpawn.com/texts/pointinpoly/default.html
(On that page is another algorithm that can also work for triangles)
Hit testing on a polygon is not so difficult to do in real time. You could use a KD-Tree for optimisation if the map is huge. Otherwise find a simple Contains method for a polygon and use that. I have one on another computer. Let me know if you'd like it.

Get points for a semi circle

The title says it.
This link(Wikipedia Midpoint Circle Algorithm) shows how to get points for a full circle, now I need it to be for a semi circle(an arc?).
It semi circle should be facing up, like in this image(Check this image)
But the bottom of the circle should be open!
For those who might think this is homework, it's not.
I'm working on a game in Xna and I want the 'rocket' that comes out of the rocket launcher to go through a certain path, a semicircle.
I don't think that algorithm is the right way to do what you want to do: describe a path. That algorithm is for plotting pixels along the path rather than describing it as such. Instead, trigonometry is probably what you want. Increase the angle from one point to another, step by step. A circle is 2π radians, so half a circle is π radians.
This should provide what you need to describe the arc. http://mathworld.wolfram.com/Trigonometry.html
Just use the Midpoint Circle Algorithm for values where y > 0 (assuming that the circle's midpoint is at (0, 0)). Anything below that is "open"

Efficient way of checking if a location is inside a rectangular perimeter?

I'll first introduce the problem: I'm developing an application where I've to show a map field, and overlay markers and lines. However, in BlacBerry OS 5.0, the only MapField available in the API does not provide means to overlay stuff, only show the map at a location. It also provides methods to transform screen coordinates (pixels) to/from WGS84 coordinates. These methods might be computationally expensive.
So to paint my own items, I need to extend this class and override its paint() method. The extending class will also hold a collection of locations.This is how the overriden method would look like (I'll use Java here):
public void paint (Graphics g) {
super.paint(g); //draws the map
//TODO
//Draw placemarks. The placemarks are basically holder objects
//(for latitude and longitude) stored in a collection in this class.
}
However, to paint these objects in the screen we should first convert the placemark locations (lat, long) to screen coordinates (x,y in pixels). This cannot be done in advance since the map is not static, so it is able to scroll and zoom in an out. This is why in each paint loop we should paint at least THE VISIBLE OBJECTS. That said, my question is:
Given a rectangular perimeter where the corners are geographic locations (the transformed four corners of the portion of the map currently displayed), is there a fast method to loop on every placemark in the collection and determine if they are visible or not?
I don't need this test to be 100% accurate, I don't mind if a few locations outside the screen are painted. But as the placemark collection can contain many elements (< 100), and the paint method will be called on each screen repaint, trying to paint every location in the collection without checking if it is visible or not could affect performance and introduce lag when the user interacts with the map.
Before you try to provide a naive answer, notice that this is not a simple geometrical problem: We're working with geographic coordinates, not with integer screen coordinates. The world doesn't end in longitude +180, or in latitude +90. This function should work in the poles and in the ecuator, so I need it to work also when we have a transition line (from -180 to +180, or from -90 to +90, or both lines) intersecting with the rectangle. As the logic can get complex, I'd like to know if there's an existing algorithm or open source library where this has already been done and tested, rather than implementing my own one.
I could also first convert every location in the collection to screen coordinates, and then easily check against a rectangle composed only by positive screen coordinates (starting from x=0, y=0), but as the transformation functions might be expensive, I think it is better to transform only 4 points in each refresh (the visible map corners) than an indeterminate number of placemarks.
Any other approach or idea would also be appreciated.
Thanks in advance.
Just a primitive idea: Take two opposite corners of your "rectangle", e.g. the upper left one and the lower right one. Transform both corners to Cartesian space coordinate (x,y,z) by:
x = cos[long] cos[lat]
y = sin[long] cos[lat]
z = sin[lat]
Both of the (x,y,z) coordinates are unit vectors (imagine the center of the sphere being in (0,0,0), and the vectors being arrows from there to the surface). Find the "middle" of your map area as the normed average of the two corner vectors (add as vectors, then divide by length of sum vector to make sure you have a new unit vector). When you have the middle (xMiddle,yMiddle,zMiddle), for every placemark coordinate transformed into cartesian (x,y,z), use the dot product with (xMiddle,yMiddle,zMiddle) as a measure of the closeness to the middle.
Now include every placemark whose dot product with (xMiddle,yMiddle,zMiddle) is greater than the upper left corner's dot product with (xMiddle,yMiddle,zMiddle).
This should give you all placemarks inside a circular disk centered at "middle".
You could at least rule out a large number of candidates with a naive box check in map coordinate space. There are probably three main cases here. Either there's a pole is in the rectangle or there isn't. If the pole isn't visible, either the rectangle crosses the +/-180 degrees line or not. There can't be any +/-90 line, because that would put together north and south pole and you're not working with a 4D map, are you? ;-)
Case 1, a pole is visible:
If it's the north pole, figure out which of the corners has the smallest latitude. Any latitude smaller than that is likely off-screen. If it's the south pole just reverse the logic, i.e. use the largest latitude and exclude any items with a greater latitude.
I know, having the pole in one corner and the equator in another means you still include an entire hemisphere. But at least you can cheaply exclude the other half.
Case 2, no pole, not crossing the +/-180 longitude line:
Find the min/max longitude and latitude values and use those for a simple box check. Anything outside the box is off-screen.
Case 3, no pole, but crossing the +/-180 longitude line:
Same as above for latitude. For longitude, find the longitudes furthest away from +180 and -180 respectively. Exclude any items with a latitude outside the min/max or between the two furthest longitudes you found.
The cases 2 and 3 should be able to rule out enough candidates to make a brute-force check for the others feasible. Case 1 may require further post-processing, but I'm afraid that part is a bit too complicated for me if you want something sophisticated.
I suppose you could somehow find an off-screen point closest to the pole if the pole is further away from the center of the screen. Then somehow construct a triangle-like shape with one corner at that point and make it as large as possible without touching the screen rectangle.
I think you just need to Convert your rectengular perimeter to geographic coordinates.
Instead of trying to convert the geogrpahic coordinates to screen coordinates.
I'm sorry that the answer is naive - but you do you ask about logic.
And so the logical thing I visualize is a window sliding on a spehere and that means you need to have that window geographical coordinates as your points of reference.
After you process that "3d" information you can start rendering your view.

Draw 2D Curve in XNA

Is there any way to generate a Curve class and then draw that curve in 2D on the screen in XNA?
I want to basically randomly generate some terrain using the Curve and then draw it. Hoping that I can then use that curve to detect collision with the ground.
It sounds like what you want is the 2D equivalent of a height-map. I'd avoid making a true "curve" and simply approximate one with line segments.
So basically you'll have an array or list of numbers that represent the height of your terrain at a series evenly spaced (horizontally) points. When you need a height between two points, you simply linearly interpolate between the two.
To generate it - you could set a few points randomly, and then do some form of smooth interpolation to set the rest. (It really depends on what kind of curve you want.)
To render it you could then just use a triangle strip. Each point in your height-map will have two vertices associated with it - one at the bottom of the screen, the other at the height of that point in the height-map.
To do collision detection - the easiest way is to have your objects be a single point (it sounds like you're making a artillery game like Scorched Earth) - simply take the X position of your object, get the Y position of your terrain at that X position, if the Y position of your object is below the terrain, set it so that it is on the terrain's surface.
That's the rough guide, anyway :)

Categories