I have a programming question with some math weight. I have a map with shapes(polylines) drown on it. I can take the screen coordinates of that shapes and translate them to map coordinates and reverse. I am capturing mouse position and moving around the map. How can I recognize if I come in proximity to another shape drown on the map while I am moving the mouse. I was thinking to create a radius of points around the mouse cursor, then constantly looping trough available shapes (I imagine I can load their coordinates in arrays) for a match. However that will be very slow I think. The point is that when I am in proximity (for example 15px) I will snap the muse position to that close shape. Any suggestions?
Now - if you really want to make it perfect - you can calculate the distance of a cursor to each line segment.
For each line segment (defined by points D and E)
Calculate line formula for segment DE in format:
Ax + By + C = 0
A = D.y - E.y
B = E.x - D.x
C = (plug in point D) = -1 * (A * D.x + B * D.y)
Now plug in your cursor position to the formula:
A * cursor.x + B * cursor.y + C = YOUR DISTANCE TO THE LINE SEGMENT
*One thing - this is distance to the unbounded line. You now want to make sure that you are between the two segment points. So make sure the angles in your cursor, D, E triangle are all < 90 degrees. A number of ways to do that, look into the dot product formula to learn a fast one.
Now if anlges are less than 90, use the distance to the line, else, use the min distance to either point of segment (D & E). Now you have a complete snap to lines functionality.
If you have every point / line segment of the shapes (which you should with the polylines), here is a possible quick and simple routine:
For each shape
Figure center of shape by averaging each constituent point (i.e. - for a pentagon, add all five point.x up, divide by 5 - do same for all point.y). Call this average shape.x and shape.y. Use distance formula to figure proximity to your mouse. (Mouse.x - Shape.x)^2 + (Mouse.y - Shape.y)^2... you don't have to take the square root of that since you are only interested in the closest shape.
Keep track of the minimum distance "squared" for each shape. The minimum is your closest shape center.
If you want snap to behavior with a maximum range, just also make sure the distance squared is < pixel distance squared.
If you want to make it very effiecient, the shape centers do not need to be constantly refigured, just calculated once. The center will scale and translate the same as any other point if you are converting between screen space and other coordinates as you mentioned.
Related
I have the following Figure and the equations:
Three Axis for measuring tilt
Equations for measuring tilt
The body on the Figures is a tri-axial accelerometer sensor, which measures accelaration in meters/seconds².
The goal is to calculate the tilt of the following angles using acceleration values:
ρ: angle of the X-axis relative to the ground (orange line);
Φ: angle of the Y-axis relative to the ground (orange line);
θ: angle of the Z-axis relative to the gravity (green line).
Could someone explain how to find equations 1,2 and 3 from the figure above?
Source of the equations and figure: https://www.thierry-lequeu.fr/data/AN3461.pdf
There is another similar and more detailed source that uses the same equations, but I also could not understand how to find them: https://www.analog.com/en/app-notes/an-1057.html
I have already implemented them and it is working, I just want help to understand how to obtain the equations. Here is the code:
let pitch = Math.atan(ax / Math.sqrt((Math.pow(ay,2) + Math.pow(az,2))) );
let roll = Math.atan(ay / Math.sqrt((Math.pow(ax,2) + Math.pow(az,2))) );
let theta = Math.atan(Math.sqrt((Math.pow(ax,2) + Math.pow(ay,2))) /az);
Thanks in advance.
This is the Pythagorean theorem, finding the 2D distance between 0,0 and a point represented by the two numbers given. If we assign that to a new function it may be clearer:
distance(a, b) { return sqrt((pow(a,2) + pow(b,2))) }
Then angles are calculated by using the inverse tangent function with a distance from that function representing one side of the triangle. For example, the pitch in your question divides the x acceleration by the distance between 0,0 and the acceleration in the YZ plane.
pitch = atan(x / distance(y, z))
I am trying to figure out the (x,y) position of the s2 node from the given example.
1
With trilateration I was able to calculate the first node s1 position based on the fixed anchors. Now I am trying to calculate the s2 node possible coordinates, what I have is:
Coordinates of two points:
A2:{y:0,x:4}
S1:{y:2,x:2}
Distances:
A2-S2: 2
S1-S2: 2
A2-S1: 2
Is there a way to calculate the possible positions of the s2 node based on this data in JavaScript? This should work on any type of triangle.
Update:
I think I found a solution, I can threat the 2 known position as the centre of two circle and the distances to the unknown point as radius, than I have to calculate the intersection of the two circle to get the possible coordinates.
A JavaScript function that returns the x,y points of intersection between two circles?
You have two known points A and B, unknown point C and distances dAC and dBC (dAB is useless). So you can build equation system
(C.X - A.X)^2 + (C.Y - A.Y)^2 = dAC^2
(C.X - B.X)^2 + (C.Y - B.Y)^2 = dAB^2
and solve it for C.X and C.Y (there are possible two, one and zero solutions).
Note that it is worth to shift coordinates by (-A.X, -B.X) to get simpler equations and solution, then add (A.X, B.X) to the solution coordinates
I'm trying to find the co-ordinates of an edge of a square from an imaginary line from the centre of the square that goes out on a variable angle. Where that line intercepts with the edge of the square is the co-ordinates I need.
For example sake, the square is 50px X 50px the center co-ordinates are (10,10) and the angle of the line from the center is on a 45 degree angle clockwise, the end of this line should not extrude the square and I'm trying to find the x,y co-ordinates of the end of this line.
What am I using this for, I want to be able to rotate a liner gradient fill in a rect() as you would do so in photoshop. I'm also not wanting to use a library as I'm trying to "reinvent the wheel" as I find it the best way to learn for my own sake.
I'm doing this in Javascript.
Thanks in advance for any help
You have to subdivide the rectangle if four sectors, then determine in which sector your line lies. One way to do that is checking the angle value with 90°, 180° and 270° using plain if statements.
Once you have the angle's sector, you have to compare the line's angle against the rectangle's diagonal angle, so you could determine the edge your line is colliding with.
Once you've determined the collision edge you get one of the collision coordinates for free (left-x, right-x, top-y or lower-y), the another coordinate can be obtained using trigonometry (the tangent relation).
You'll end up with two basic cases in every sector, one takes the opposite leg for the right triangle that forms for the collision with one of the vertical edges and the other takes the adjacent leg. Here is an example for the first sector (the upper right quadrant)
if (lineAngle < rectDiagAngle) {
// For this collision you have the x coordinate, is the same as the
// right edge x coordinate
colX = rectX + rectW;
// Now you need to find the y coordinate for the collision, to do that
// you just need the opposite leg
oppositeLegLength = Math.tan(lineAngle) * (rectW / 2);
colY = rectCenterY - oppositeLegLength;
} else {
// The line collides with the top edge
// For this collision you have the y coordinate, is the same as the
// top edge y coordinate
colY = rectY;
// Now you need to find the x coordinate for the collision, to do
// that you just need the adjacent leg
adjacentLegLength = (rectH / 2) / Math.tan(lineAngle);
colX = rectCenterX + adjacentLegLength;
}
This fiddle takes the angle, calculates the collision point and then draws a line from the rectangle center to the collision point.
I am implementing a map-like interface for a personal project, in Javascript with HTML5 canvas, and I am mostly looking for ideas on how I could properly tessellate all 2D polygon sides with equal-length rectangles per side. Before explaining further, here are two actual screenshots of the existing interface:
(source: mavrosxristoforos.com)
As you can see, there are "n" rectangles on each of the polygon sides, with length equal to "side's length" divided by "n", and width their length divided by 2. The number of rectangles is user-set.
The actual data I have is: the polygon corner coordinates and the number of rectangles.
The sides are always populated clockwise.
At the moment, the pseudocode for how they are drawn, looks like this:
RECT_LENGTH = polygon_side_length / count_of_rectangles;
i = first_corner_of_the_polygon_side;
for ( j = 0; j < count_of_rectangles; j++) {
move pen to i;
point1 = i + RECT_LENGTH * right_angle_on_polygon_side_slope;
line to point1;
point2 = point1 - RECT_LENGTH * polygon_side_slope;
line to point2;
i += RECT_LENGTH * polygon_side_slope;
line to i;
}
It is pretty obvious from the code, that it doesn't take into consideration anything other than the polygon side slope, which is the angle from the horizontal axis, measured in -π (pi) to +π, calculated from the two corner coordinates.
There are mainly three appearance problems in these screenshots:
In the upper screenshot, on the left, the big rectangle goes out of the polygon side.
In the upper screenshot, on the bottom right, the rectangles overlap (also on other corners, but that particular one looks completely unnatural).
In the lower screenshot, on the top corner, both sides' rectangles get out of the original polygon.
As a solution, I thought that I could search for a line segment intersection between the current line being drawn and the polygon sides, as well as the previous rectangle, but that doesn't feel right, and it would perform quite slow.
As already mentioned, any idea is welcome. I am not a native English speaker, so please feel free to correct me on my English.
Thank you for your time!
EDIT: I wouldn't mind it if the last rectangle became a trapezoid, just to completely cover the polygon side.
Since you're using rectangles you just can cover right-angled areas. So you have to leave some area of polygons uncovered. You have to reduce the actual length of edges like this:
In this solution you can reduce length of edges just form heads which meet an acute angle. With Alpha as the inner angle of corner, the reduction amount would be Rectangle.Width / Tan(Alpha). It keeps rectangles inside polygon but wont solve the overlap problem.
To prevent rectangles from overlapping you have to leave more area uncovered:
To do this you have to reduce the length of edge form both heads by Rectangle.Width / Tan(Alpha / 2) (Alpha may differ at each corner).
But all of these wont help since width of rectangle is unknown. In fact width of rectangle is calculated by length of edge itself, and we are using it to calculate the length of edge!!
So we have a mathematical problem here:
Known:
L1: actual length of edge
N: number of divisions
Alpha & Beta: half of inner angle of head corners
Unknown:
L2: reduced length of edge
W: width of rectangles
We can form two equations:
(1): L2 = 2 * N * W
(2): L2 = L1 - (W / Tan(Alpha) - (W / Tan(Beta)
By solving them we can find W:
W = L1 / (2 * N + Cot(Alpha) + Cot(Beta))
All these are true in convex polygons. If either head corners of edge are concave you can replace their inner angle with Pi / 2 to prevent reduction from those corners.
Please recheck everything! Considering your lovely UI, I suppose you can handle trigonometric calculations for finding start and end point of rectangles.
I have a slice of a circle (that is made of moveTo,lineTo,arc,etc) and need to find the middle point of the slice.
What is the math behind finding the point shown in the image below?
It looks "centroid" of the sector to me.
The co-ordinates of it (with x axis along the radius passing through the centroid and origin at the centre)
centroidX = (4/3)r(sin(A)/A)
centroidY = 0
where 'A' is the angle made by the arc at the centre(in radians) and 'r' is the radius.
EDIT:
This is sort of a formula which can be easily derived.
Geometric Centroid of any shape is average(weighted mean) of all it's points.
In physics, centroid(AKA centre of mass) of an object is the point at which the mass of the whole object can be assumed to be concentrated(eg, the object can be balanced on a needle at the centroid). There are formulae which can be directly used for regular shapes. For irregular shapes, it is calculated by integration.
It's basic logic is adding x co-ordinates of all the points and dividing by total no. of points, which gives x co-ordinate of the centroid and similar for y co-ordinate.
As the points on a shape are not discrete, integration is used.
Let C is center point, P1 and P2 are points at circumference, and slice angle is smaller then Pi (180 deg).
One possibility:
X = C + Radius/2 * UnitVector(P1 + P2 - 2*C)
Another:
X = 1/3 * (P1 + P2 + C)
(It depends on exact requirements)