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.
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 have a 500 pixel by 500 pixel image that I am using to pull data from a 250,000 index array where each index represents 1 pixel.
The user is able to draw a rectangle at any orientation, and I am capturing the coordinates for each corner.
I am trying to capture each pixel within the rectangle to reference the data array and extract the related data.
I looked at Bresenham algorithm in Javascript and while I can get all the points between each of the coordinates using this solution, I am unable to loop through these points as the paths do not always contain the same number of pixels.
An example of the values I'm looking for using the following coordinates would be:
corner1 = [100,100]
corner2 = [100,105]
corner3 = [105,105]
corner4 = [105,100]
And the result (sort order is not important):
pixelsInRectangle = [
[100,100],[100,101],[100,102],[100,103],[100,104],[100,105],
[101,100],[101,101],[101,102],[101,103],[101,104],[101,105],
[102,100],[102,101],[102,102],[102,103],[102,104],[102,105],
[103,100],[103,101],[103,102],[103,103],[103,104],[103,105],
[104,100],[104,101],[104,102],[104,103],[104,104],[104,105],
[105,100],[105,101],[105,102],[105,103],[105,104],[105,105]
]
One set of coordinates I'm trying to solve for are:
corner1 = [183,194]
corner2 = [190,189]
corner3 = [186,184]
corner4 = [179,190]
Any recommendations would be greatly appreciated!
If rectangle is not axis aligned:
Sort vertices by Y-coordinate.
Get the lowest one. From two next Y-coordinates choose left and right ones.
Start simple line rasterization scan along left edge and along right edge simultaneously: for current integer Y value calculate corresponding rounded X-coordinate for left edge, for right edge, and output all horizonatal line between (xleft, y)-(xright,y)
For edge between vertices (x0,y0)-(x1,y1) formula is
x = x0 + (x1-x0)*(y-y0)/(y1-y0)
(example for triangle exploiting the same technique)
When some vertex is reached, change equation of corresponding edge, continue.
Using this way, you fill triangle, parallelogramm, another triangle (or just two triangles if two vertices share the same Y)
(You can use Bresenham or DDA, or another line rasterization algorithm if necessary)
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 would like draw 3D points represented in image to 3D rectangle. Any idea how could I represent these in x,y and z axis
Here projection type is orthographic.
Thanks
Okay. Let's look at a simple example of what you are trying to accomplish it, and why this is such a complicated problem.
First, lets look a some projection functions. You need a way to mathematically describe how to transform a 3D (or higher dimensional) point into a 2D space (your monitor), or a projection.
The simpiest to understand is a very simple dimetric projection. Something like:
x' = x + z/2;
y' = y + z/4;
What does this mean? Well, x' is you x coordinate 2D projection: for every unit you move backwards in space, the projection will move that point half that many units to the right. And y' represents that same projection for your y coordinate: for every unit you move backwards in space, the projection will move that point a quarter unit up.
So a point at [0,0,0] will get projected to a 2d point of [0,0]. A point at [0,0,4] will get projected to a 2d point of [2,1].
Implemented in JavaScript, it would look something like this:
// Dimetric projection functions
var dimetricTx = function(x,y,z) { return x + z/2; };
var dimetricTy = function(x,y,z) { return y + z/4; };
Once you have these projection functions -- or ways to translate from 3D space into 2D space -- you can use them to start draw your image. A simple example of that using js canvas. First, some context stuff:
var c = document.getElementById("cnvs");
var ctx = c.getContext("2d");
Now, lets make a little helper to draw a 3D point:
var drawPoint = (function(ctx,tx,ty, size) {
return function(p) {
size = size || 3;
// Draw "point"
ctx.save();
ctx.fillStyle="#f00";
ctx.translate(tx.apply(undefined, p), ty.apply(undefined,p));
ctx.beginPath();
ctx.arc(0,0,size,0,Math.PI*2);
ctx.fill();
ctx.restore();
};
})(ctx,dimetricTx,dimetricTy);
This is pretty simple function, we are injecting the canvas context as ctx, as well as our tx and ty functions, which in this case our the dimetric functions we saw earlier.
And now a polygon drawer:
var drawPoly = (function(ctx,tx,ty) {
return function() {
var args = Array.prototype.slice.call(arguments, 0);
// Begin the path
ctx.beginPath();
// Move to the first point
var p = args.pop();
if(p) {
ctx.moveTo(tx.apply(undefined, p), ty.apply(undefined, p));
}
// Draw to the next point
while((p = args.pop()) !== undefined) {
ctx.lineTo(tx.apply(undefined, p), ty.apply(undefined, p));
}
ctx.closePath();
ctx.stroke();
};
})(ctx, dimetricTx, dimetricTy);
With those two functions, you could effectively draw the kind of graph you are looking for. For example:
// The array of points
var points = [
// [x,y,z]
[20,30,40],
[100,70,110],
[30,30,75]
];
(function(width, height, depth, points) {
var c = document.getElementById("cnvs");
var ctx = c.getContext("2d");
// Set some context
ctx.save();
ctx.scale(1,-1);
ctx.translate(0,-c.height);
ctx.save();
// Move our graph
ctx.translate(100,20);
// Draw the "container"
ctx.strokeStyle="#999";
drawPoly([0,0,depth],[0,height,depth],[width,height,depth],[width,0,depth]);
drawPoly([0,0,0],[0,0,depth],[0,height,depth],[0,height,0]);
drawPoly([width,0,0],[width,0,depth],[width,height,depth],[width,height,0]);
drawPoly([0,0,0],[0,height,0],[width,height,0],[width,0,0]);
ctx.stroke();
// Draw the points
for(var i=0;i<points.length;i++) {
drawPoint(points[i]);
}
})(150,100,150,points);
However, you should now be able to start to see some of the complexity of your actual question emerge. Namely, you asked about rotation, in this example we are using an extremely simple projection (our dimetric projection) which doesn't take much other than an oversimplified relationship between depth and its influences on x,y position. As the projections become more complex, you need to know more about your relationship/orientation in 3D space in order to create a reasonable 2D projection.
A working example of the above code can be found here. The example also includes isometric projection functions that can be swapped out for the dimetric ones to see how that changes the way the graph looks. It also does some different visualization stuff that I didn't include here, like drawing "shadows" to help "visualize" the actual orientation -- the limitations of 3D to 2D projections.
It's complicated, and even a superficial discussion is kind of beyond the scope of this stackoverflow. I recommend you read more into the mathematics behind 3D, there are plenty of resources, both online and in print form. Once you have a more solid understanding of the basics of how the math works then return here if you have a specific implementation question about it.
What you want to do is impossible to do using the method you've stated - this is because a box - when rotated in 3 dimensions won't look anything like that diagram of yours. It will also vary based on the type of projection you need. You can, however get started using three.js which is a 3D drawing library for Javascript.
Hope this helps.
How to Draw 3D Rectangle?
posted in: Parallelogram | updated on: 14 Sep, 2012
To sketch 3 - Dimensional Rectangle means we are dealing with the figures which are different from 2 – D figures, which would need 3 axes to represent them. So, how to draw 3D rectangle?
To start with, first make two lines, one vertical and another horizontal in the middle of the paper such that they represent a “t” letter of English. This is what we need to draw for temporary use and will be removed later after the construction of the 3 – D rectangle is complete. Next we draw a Square whose measure of each side is 1 inch. Square must be perfect in Geometry so that 90 degree angles that are formed at respective corners are exact in measure. Now starting from upper right corner of the square we draw a line segment that will be stretched to a measure of 2 inches in the direction at an angle of 45 degrees. Similarly, we repeat the procedure by drawing another Line Segment from the upper left corner of the square and stretching it to 2 inches length in the direction at an angle of 45 degrees. These 2 line segments are considered to be the diagonals with respect to the horizontal line that we drew temporarily in starting. Also these lines will be parallel to each other. Next we draw a line that joins the end Point of these two diagonals.
Next starting from the very right of the 2 inch diagonal end point, draw a line of measure 1 inch that is supposed to be perpendicular to the temporary horizontal line. Next we need to join the lower left corner of the square with end point of the last 1’’ line we drew in 4th step and finally we get our 3 - D rectangular. Now we can erase our initial “t”. This 3- D rectangle resembles a Cuboid.
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.