I want to draw either the lower or the upper half of an elliptical arc using Win2D in a C++/winrt app. I can draw the curve, but it includes a diagonal line at its start that looks as if I had begun with a straight line segment - as if the figure didn't begin at the arc but rather some distance down and to the right. How I can restrict drawing to just the arc? Here is the code and an image of the result:
float2 arcSize(100, 6);
auto pathBuilder = CanvasPathBuilder(drawingSession.Device());
pathBuilder.BeginFigure(244, 175);
//Starting at 3 o"clock, sweep pi radians, that is, to 9:00
pathBuilder.AddArc(arcSize,50,6,0.0, 3.14);
pathBuilder.EndFigure(CanvasFigureLoop::Open); //Don't close path
auto geometry = CanvasGeometry::CreatePath(pathBuilder);
session.DrawGeometry(geometry,244, 175, Colors::Black(),1.5);
OK, thanks to that hint from Inspectable I have the solution: the problem lies in where the path begins. In my code I had mistakenly used the proposed arc size as the first argument to AddArc when really that should be the arc center coordinates. And the BeginFigure in the case of this arc must be the point lying at the right edge, at what would be 3:00 in a circle. With the ArcCenter correct in relation to the BeginFigure then AddArc doesn't draw the extra line.
[Update:] p.s. The x and y coordinates for the DrawGeometry call should be zero in this case; that draws it at its original coordinates from BeginFigure, not offset. Maybe this p.s can gain me another -1 for this question.
Related
I have a UIView, which I'm drawing manually in the 'drawRect'-Function.
It is basically a coordinate system, which has 'Values' on the Y-Axis and 'Time' on the 'X-Axis'.
Due to space issues, I want the Timestamps to be vertical, instead of horizontal.
For this purpose, I use:
CGContextSaveGState(ctx); //Saves the current graphic context state
CGContextRotateCTM(ctx, M_PI_2); //Rotates the context by 90° clockwise
strPos = CGContextConvertPointToUserSpace(ctx, strPos); //SHOULD convert to Usercoordinates
[str drawAtPoint:strPos withFont:fnt]; //Draws the text to the rotated CTM
CGContextRestoreGState(ctx); //Restores the CTM to the previous state.
ctx (CGContextRef), strPos (CGPoint) and str (NSString) are variables, that have been initialized properly and correctly for 'horizontal text', with a width of the text height.
While this code works flawlessly on the iPhone 3, it gives me a complete mess on the iPhone 4 (Retina), because the CGContextConvertPointToUserSpace function produces completely different results, even though the coordinate system of the iPhone is supposed to remain the same.
I also tried using CGAffineTransform, but only with the same results.
To summarize my question: How do I draw a text to a calculated position in the parent coordinate system (0, 0 being top left)?
After studying the Apple docs regarding Quartz 2D once more, I came to realize, that the rotation by Pi/2 moves all my writing off screen to the left.
I can make the writing appear in a vertical line by translating the CTM by +height.
I'll keep trying, but would still be happy to get an answer.
Edit: Thanks to lawicko's heads-up I was able to fix the problem. See Answer for details.
I would like to thank lawicko for pointing this out.
During my tests I made two mistakes...but he is of course correct. Using CGContextShowTextAtPoint is the most simple solution, since it doesn't require the rotation of the entire CTM.
Again, THANK you.
Now, for the actual answer to my question.
To draw a rotated text at position x/y, the following code works for me.
CGAffineTransform rot = CGAffineTransformMakeRotation(M_PI_2); //Creates the rotation
CGContextSelectFont(ctx, "TrebuchetMS", 10, kCGEncodingMacRoman); //Selects the font
CGContextSetTextMatrix(ctx, CGAffineTransformScale(rot, 1, -1)); //Mirrors the rotated text, so it will be displayed correctly.
CGContextShowTextAtPoint(ctx, strPos.x, strPos.y, TS, 5); //Draws the text
ctx is the CGContext, strPos the desired position in the parent coordinate system, TS a char array.
Again, thank you lawicko.
I probably would've searched forever if not for your suggestion.
Maybe this answer will help someone else, who comes across the same problem.
I'm drawing a line on iOS by stroking a path onto a CALayer. How can I stroke this line with an increasing lineWidth (stroke width), so that the left end of the line is thinner than the right end? (It really has to be a line, not a shape or closed path, since I'm going to be using the strokeEnd property.)
Thank you for your help!
Use a draw function. It's pretty annoying to get used to at first, but it does its job. If you need anymore help just leave comment
-(void)draw{
float lineHeight = 5;//change this as you see fit, like set it equal to an incrementing/decrementing variable of your choice...
glEnable(GL_LINE_SMOOTH);
glLineWidth(lineHeight); // change this as you see fit
glColor4ub(255,255,255,255); // change these as you see fit :)
ccDrawLine(ccp(10,310), ccp(30,310)); // these numbers are probably off, you'll have to mess with these to get it in the right position :)
[super draw];
}
I have 3 sprites that all have the same angle, so I'm just going to say arm sprite.
Arm sprite's angle, at the moment, is equal to one point1 (60,60 but this does not matter)
to another point2, the point where the player thumb pressed.
During the ccTime function I update everything, the angles and stuff. So whenever the user touches a spot on the screen, the angle is immediately changed and the arm's angle is equal to the vector from point1 to point2.
I don't want the angle change to take .016 seconds to complete (ccTime gets called every 1/60'th of a second). What I want is for the angle to increment/decrement faster/slower depending on how far away the new vector is from the current vector. Basically I want the arm to raise/lower at a certain speed, maybe accelerate a bit, depending on the vector.
I've tried many times to make it work, but I'm not getting anywhere. Please help me, rotation can go from 90 degrees straight up to almost 180 degrees straight down (the angles in cocos2d are changed, however, so I had to add 90 here and there).
If you need anymore information, just leave a comment and I'll give you the info asap.
You should set the new angle as a destinationAngle then on your update loop:
//Instead of checking for equality, you might want to check the angle is close enough, e.g. if they are withing 1 degree of each other e.g.(if (abs(destinationAngle - angle) < 1)
if (angle != destinationAngle)
{
//move towards destination
angle += ((destinationAngle - angle) / 10.0f);
}
http://u.snelhest.org/i/2010/07/06_3754.png
I'm trying to draw this picture in JES, Jython.
I've forgotten some of the basic math from school, so it's kind of difficult .
I've done the full circle, but i'm not sure how to continue from there.
Each rectangle, half-circle and circle is inset by 10 pixels, and the picture is a 200x200 square.
addRect, addOval and addArc are the given hints.
addArc(picture, startX, startY, width, height, start, angle[, color]):
addOval(picture, startX, startY, width, height[, color]):
addRect(picture, startX, startY, width, height[, color]):
(I'm assuming this is a homework problem)
Can you draw the shape out by hand and document what you're doing? Write out the start coordinate, apex and end coordinate of each arc, or at least as many as you need to see a pattern. That's always a good place to start because if you can draw it out and get some of the coordinates, all you'll need to do is convert to JES syntax.
Since the changes in the arc sizes and positions are regular over the figure, you should be able to use a loop to draw each half circle. You can do a single loop that draws even numbered arcs opening down and odd numbered arcs opening up but I think it's easier to have one loop for the arcs opening up and a second for arcs opening down.
Let's say I have circle bouncing around inside a rectangular area. At some point this circle will collide with one of the surfaces of the rectangle and reflect back. The usual way I'd do this would be to let the circle overlap that boundary and then reflect the velocity vector. The fact that the circle actually overlaps the boundary isn't usually a problem, nor really noticeable at low velocity. At high velocity it becomes quite clear that the circle is doing something it shouldn't.
What I'd like to do is to programmatically take reflection into account and place the circle at it's proper position before displaying it on the screen. This means that I have to calculate the point where it hits the boundary between it's current position and it's future position -- rather than calculating it's new position and then checking if it has hit the boundary.
This is a little bit more complicated than the usual circle/rectangle collision problem. I have a vague idea of how I should do it -- basically create a bounding rectangle between the current position and the new position, which brings up a slew of problems of it's own (Since the rectangle is rotated according to the direction of the circle's velocity). However, I'm thinking that this is a common problem, and that a common solution already exists.
Is there a common solution to this kind of problem? Perhaps some basic theories which I should look into?
Since you just have a circle and a rectangle, it's actually pretty simple. A circle of radius r bouncing around inside a rectangle of dimensions w, h can be treated the same as a point p at the circle's center, inside a rectangle (w-r), (h-r).
Now position update becomes simple. Given your point at position x, y and a per-frame velocity of dx, dy, the updated position is x+dx, y+dy - except when you cross a boundary. If, say, you end up with x+dx > W (letting W = w-r), then you do the following:
crossover = (x+dx) - W // this is how far "past" the edge your ball went
x = W - crossover // so you bring it back the same amount on the correct side
dx = -dx // and flip the velocity to the opposite direction
And similarly for y. You'll have to set up a similar (reflected) check for the opposite boundaries in each dimension.
At each step, you can calculate the projected/expected position of the circle for the next frame.
If this lies outside the rectangle, then you can then use the distance from the old circle position to the rectangle's edge and the amount "past" the rectangle's edge that the next position lies at (the interpenetration) to linearly interpolate and determine the precise time when the circle "hits" the rectangle edge.
For example, if the circle is 10 pixels away from the rectangle's edge, then is predicted to move to 5 pixels beyond it, you know that for 2/3rds of the timestep (10/15ths) it moves on its orginal path, then is reflected and continues on its new path for the remaining 1/3rd of the timestep (5/15ths). By calculating these two parts of the motion and "adding" the translations together, you can find the correct new position.
(Of course, it gets more complicated if you hit near a corner, as there may be several collisions during the timestep, off different edges. And if you have more than one circle moving, things get a lot more complex. But that's where you can start for the case you've asked about)
Reflection across a rectangular boundary is incredibly simple. Just take the amount that the object passed the boundary and subtract it from the boundary position. If the position without reflecting would be (-0.8,-0.2) for example and the upper left corner is at (0,0), the reflected position would be (0.8,0.2).