It is stated, that to rotate a line by a certain angle, you multiply its end point coordinates by the matrix ({Cos(a), Sin(a)} {-Sin(a) Cos(a)}), where a is rotation angle. The resulting two numbers in matrix will be x and y coordinates of rotated line's end point. Rotation goes around line's start point.
Simplifying it, new coordinates will be {x*Cos(a) - y*Sin(a)} for x and {x*Sin(a) + y*Cos(a)} for y.
Task is to rotate a triangle, using this method. But the following code that uses this method, is giving out some crap instead of rotated image (twisted form of original triangle, rotated by "random" angle):
x0:=200;
y0:=200;
bx:=StrToInt(Edit1.Text);
by:=StrToInt(Edit2.Text);
cx:=StrToInt(Edit4.Text);
cy:=StrToInt(Edit5.Text);
a:=StrToInt(Edit3.Text);
//Original triangle
Form1.Canvas.Pen.Color:=clBlue;
Form1.Canvas.MoveTo(x0,y0);
Form1.Canvas.LineTo(bx,by);
Form1.Canvas.LineTo(cx,cy);
Form1.Canvas.LineTo(x0,y0);
//New triangle
Form1.Canvas.Pen.Color:=clGreen;
Form1.Canvas.MoveTo(x0,y0);
b1x:=Round(bx*cos(a*pi/180)-by*sin(a*pi/180));
b1y:=Round(bx*sin(a*pi/180)+by*cos(a*pi/180));
c1x:=Round(cx*cos(a*pi/180)-cy*sin(a*pi/180));
c1y:=Round(cx*sin(a*pi/180)+cy*cos(a*pi/180));
Form1.Canvas.LineTo(b1x,b1y);
Form1.Canvas.MoveTo(x0,y0);
Form1.Canvas.LineTo(c1x,c1y);
Form1.Canvas.LineTo(b1x,b1y);
end;
Well, I'm out of ideas. What am I doing wrong?
Thanks for your time.
The formula you are using rotates a point around (0, 0). To achieve the required result change your calculation to:
b1x:=x0 + Round((bx-x0)*cos(a*pi/180)-(by-y0)*sin(a*pi/180));
b1y:=y0 + Round((bx-x0)*sin(a*pi/180)+(by-y0)*cos(a*pi/180));
c1x:=x0 + Round((cx-x0)*cos(a*pi/180)-(cy-y0)*sin(a*pi/180));
c1y:=y0 + Round((cx-x0)*sin(a*pi/180)+(cy-y0)*cos(a*pi/180));
You appear to be rotating each individual line round its initial start point coordinates. So line 1 will get rotated about its start point (x0,y0); then line 2 will get rotated about bx,by; then line 3 will get rotated round cx. This will result in a twisted triangle. Instead you will need to rotate all three lines round the start point of the first line.
Related
I don't know which numbers do what in the coordinates example here. I imagine they mean things like place the top left corner at this position and the bottom right corner at this position, but I don't know which number corresponds to which position.
I've been trying to fool around with the numbers to get a small green rectangle but keep getting weird results like the following, and don't know which numbers need to be what is order to make the rectangle symmetrical and at the bottom
This is what the rectangle should look like
The height of the rectangle is 50, the height of the screen is 1000, and the width of the screen is 1700.
Here's my draw function
function love.draw()
love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates
-- These are the grounds coordinates. -11650 950 13350 950 13350 1000 -11650 1000
love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())
love.graphics.setColor(0.20, 0.20, 0.20) -- set the drawing color to grey for the blocks
love.graphics.polygon("fill", objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
love.graphics.polygon("fill", objects.block2.body:getWorldPoints(objects.block2.shape:getPoints()))
print(objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
end
As described at https://love2d.org/wiki/love.graphics, Löve's coordinate system has (0, 0) at the upper left corner of the screen. X values increase to the right, Y values increase down.
The polygon function expects the drawing mode as it's first parameter, and the the remaining (variable) parameters are the coordinates of the vertices of the polygon you wish to draw. Since you want to draw a rectangle you need four vertices/eight numbers. You do not have to list the upper left corner of the rectangle first, but that's probably the easiest thing to do.
So in your case, you want something like:
love.graphics.polygon('fill', 0, 950, 0, 1000, 1700, 1000, 1700, 950)
I've not worked with the physics system, so I'm not quite sure how it's coordinate system relates to "screen" coordinates. The values you show in the comment in your code listing seem like they should give a rectangle (although x = -11650 wouldn't be on screen). You might try experimenting without the physics system first.
Also, since the physics system in Löve is just a binding to Box2D, you might want to read its documentation (http://box2d.org/about/). Not really sure what you're trying to do with feeding shape:getPoints into body:getWorldPoints.
I have this code:
platform.window:invalidate()
function on.paint(gc)
gc:setColorRGB(0,0,0)
for i=1,8,1 do
gc:fillArc(230,(i*30)-40,30,30,45,360-(i*60))
end
end
if you look at the first iteration, where i=1, the circle should be drawn from 45° - 300° counter-clockwise. This isn't what happens. The circle is drawn from what looks like 45° to 345°, which obviously is undesirable.
Some other odd occurrences happen when drawing other circles, which makes them seem flipped, or mirrored or something like that when drawn. This oddity can be replicated by inputting different values into the 2 last arguments of fillArc(). 90 and 270 draws from 90 to 360. 180 and 270 draws from 180 to 90. Why is this occurring?
https://imgur.com/a/Miww8
I don't have a device to test this on, but from what you are describing it looks like the "end angle" argument is taken to be relative to the "start angle", so 90 and 270 will be drawn from 90 to 90+270. This would not be my reading of the documentation -- "The arc is drawn beginning at startAngle degrees and ending at endAngle." -- but it can probably be interpreted either way.
I am trying to achieve a view in which Images will placed on edge of circle.I tried to make it with CAShapeLayer and added UIImageViews but I want to create it dynamically. Any help will be appreciated.I am adding one image for example.
I would suggest you to refer this answer given by #rob_mayoff
You should create a circular bezier path with the image you want to display.Please not that this method only works if you want to have same image distributed evenly on the circle.If you want to have different image distributed evenly on circle, then you should do put more effort .
You can try in two ways:
Draw every circular bezier path by calculating their centers . And arrange them in a circular manner. You should do a little math. Please note that you have the center point (x,y) for the main circle, and place the sub circles around the center point (x,y) in such a way that distance from each sub circle center to main circle center should be same. To get the exact coordinates of lines which divide the circle , please refer to the answer. Once you get the exact coordinate, you can place the subcircle at these positions.
I will try to give a rough idea about doing this:
Consider you have a main circle whose center is at (x0,y0). And you wish to place images on this circle by dividing the circle into 'n' parts. so that you can place 'n' number of imageViews on this main circle. The 'n' parts are denoted by green lines in the below picture.
The angle between each of the green lines is 360deg/n
No we need the end point of the each green line. Which can be obtained from:
sub.x = x0 + r * cos(angle);
sub.y = y0 + r * sin(angle);
where r is the radius of main circle.
This is for one sub circle. In yoour case you have 'n' number of sub circles, so let's do a loop to get all sub circle centerpoints:
for(i = 1 to n)
{
angle = i * (360/n);
sub.x = x0 + r * cos(angle);
sub.y = y0 + r * sin(angle);
}
Now you can draw a circular bezier path at each of the 'n' sub (x,y) points
using the addArcWithCenter:center where center would be the calculated sub (x,y)
I think 1 is again the best way if you want to do everything dynamically.
I have a problem to use this bulge arc (dxf parser) function in C++ getArcDataFromBulge().
https://github.com/Embroidermodder/Embroidermodder/blob/master/libembroidery/geom-arc.c
I have my drawArc() function which need 'start angle' and 'sweep angle' parameters from this getArcDataFromBulge() function.
My drawArc() function use OpenGL 2D coordinate system with right side zero angle position and when I get values from getArcDataFromBulge() and recalculate it (0+-, 180+-, 360+-) I have something like unexpected opposite angles as results. It looks like clockwise-counterclockwise problem, but I'm think is not, I'm not sure. Do you have some idea what is going on?
For example:
tempBulge.bulge := 0.70;
arcMidAngle := RadToDeg( atan2(tempBulge.arcMidY - tempBulge.arcCenterY,
tempBulge.arcCenterX - tempBulge.arcMidX) );
After calculaton: arcMidAngle = 179.999
When I add and subtract from this point half of arc chord angle, I get start and end angles of my arc: 90°, 270° but it's not the same arc when I open dxf with some CAD software, it is opposite than origin drawing.
If you have an arc from 0° to 90°, it could be a 1/4 circle or a 3/4 circle.
You need to parse the $ANGDIR and $ANGBASE variables from the HEADER section which tells you in which direction angles are defined ($ANGDIR) and where the 0° angle starts ($ANGBASE) within that specific DXF file:
Variable Group code Description
$ANGBASE 50 Angle 0 direction
$ANGDIR 70 1 = Clockwise angles, 0 = Counterclockwise
For DXF, if $ANGBASE = 0, then 0° is on the right of the center, alike Windows.
Furthermore, in DXF, the positive Y-axis is upwards, in contrast to many Windows API's where the positive Y-axis is downwards.
I've heard that you can tilt a part by a precise amount using the .CFrame property. However, I'm unclear on how to use it. The following code does not work:
Workspace.Part.CFrame = CFrame.new(90,0,45)
It is not rotating the part by 90 degrees and 45 degrees. What am I doing wrong?
First, use the CFrame.fromEulerAnglesXYZ function to create a new CFrame pointing in the direction you wish. Then, use Vector3 math to move the CFrame into the desired position.
EG.
local cframe = CFrame.fromEulerAnglesXYZ(XRADIANS, YRADIANS, ZRADIANS)
cframe = (cframe - cframe.p) + Vector3.new(XPOS,YPOS,ZPOS)
The documentation states that a Coordinate Frame (CFrame) constructor that takes 3 parameters is defining a position offset. Therefore, your example code would move the part 90 along the x-axis and 45 along the z-axis. To perform a rotation as you attempted see the CFrame.fromEulerAnglesXYZ function.
The arguments taken specify position, not rotation
I had this trouble too when I was starting to CFrame. They are RADIANS, not DEGREES. I have written a quick CFraming guide on ROBLOX, here.
If you're struggling with radians, you should look at the ROBLOX wiki page on radians to gain a basic understanding: wiki.roblox.com/index.php/Radians
Thanks!
-pighead10
-- Rotates the part by 90 degrees. If you want to change the axis your
-- rotating it on Use a different placement such as CFrame.Angles(math.rad(90),0,0)
Workspace.Part.CFrame = Workspace.Part.CFrame * CFrame.Angles(0, math.rad(90), 0)