http://codepen.io/andrewplummer/pen/pyjjbJ
I'm trying to make a simple arc for a graph. I've read up on "A a" arc in SVG and I believe I understand the specifics, but when the arc approaches its origin point it starts slipping to the right and I can't figure out why.
The main problems seems to be here: <path d="M75 5 A70 70 0 1 1 71 6" stroke="#3f51b5"></path>. As the closing point (71 76) approaches the origin (75 5) the arc starts to shift to the right. The pen shows more details... All browsers show this behavior so it doesn't seem to be a bug.
If you need accuracy, then don't try to draw a complete 360deg arc with one path arc command. Because you don't specify the centre point when describing arcs, tiny mathematical inaccuracies between the combination of start point, end point and radiuses can cause the arc to shift around by quite a surprising amount.
I would suggest keeping your arcs to a maximum of 180 degrees. For large radiuses you may want to go even lower, and limit it to 90 degrees.
As it turns out, it's the call to Math.ceil that was causing this issue. It appears that even small changes in the final x/y position (the last 2 arguments to the svg A command) can have big effects on the resulting arc. When drawing larger arcs these smaller differences can have more exaggerated effects, so #Paul LeBeau's answer is somewhat correct. However, simply not rounding fixed the issue and renders perfectly so it seems that one arc will in fact do the trick, just don't round (rounding pixel values is kind of a force of habit for older devs used to crappy browsers).
The arc command has two flags, the attached image should explain it.
Are you trying to draw a complete circle ?
Related
I am making a platformer game with all the basic code that is usualy found in godot platformers(kinimaticbody2d,move_and_slide, etc). the problem is that the character can climb really steep slopes which I dont like.
for example the character can move up the slope shown in the picture simply by pressing left(no jumping) he just slowly slides up
but when i make the slope just a little bit steeper the character cant scale the slope.
my question is there a way to set the maximum angle of a slope that a character can climb? thx in advance
If you are using move_and_slide you need to:
Specify an up_direction vector, which goes into the second parameter of move_and_slide. Without it, everything is considered a wall, and no sliding happens. Since, you are experiencing sliding, I suspect you already have this.
And specify floor_max_angle float, which goes into the fifth parameter of move_and_slide. This controls how inclined can be a surface and still be considered a floor/slope. If a surface is more steep that this angle, it will be considerad a wall, and no sliding happens. The angle is measured between the normal of the surface and the up_direction vector provided.
By default the value of floor_max_angle is 0.785398 (it is in radians, by the way) which is equivalent to 45º.
The situation you are suggest you are using a number closer to a quarter turn (i.e π/2 - approx 1.57 - radians). Probably something like 1.2 or 1.3? You want a smaller value.
By the way, you can convert from radians to degrees with rad2deg and viceversa with deg2rad.
I'll quickly go over a couple more issues you may find along the way:
The character slides down when idle due to gravity. To prevent this, you want to set stop_on_slope to true. This is the third parameter of move_and_slide.
The character have jitter and move more than desired when going down the slope with user input (caused by very little jumps usually perceived as jitter). And this is why you would want to move_and_slide_with_snap, which has an extra snap vector parameter which allows you to specify a direction the character should stick to the ground while moving. By the way, you may want to use get_slide_collision to figure out on what surface the character did slide, if any, and what is its normal.
I have this fun idea of a project i'd like to do, but i'm not really sure about the math part of it. Here is the idea:
Make a plastic card that would simulate a 9 finger multitouch gesture when it is held against a capacitive screen
Based on the "9 finger" placement, determine some sort of a unique string and use it as an encryption/decryption key for an app
This way i could just open an app, touch the screen with the card and it would get authorized.
But here's the problem:
It shouldn't matter where you place the card on a screen, because the card would be pretty small to fit various screen sizes
The rectangle in which we can randomly position the 9 "fingers" would optimally be 4.5cm x 3cm
The "finger" itself is only recognized as a touch if it is about a 6mm circle (not sure if this can be made smaller)
I figured we could find the left-top "finger" and get every other "finger's" X and Y difference from it. Then concatenate the resulting numbers into a string and use it as a decryption/encryption key. So basically:
key = concat(X2 - X1, Y2 - Y1, X3 - X1, Y3 - Y1, ...)
But i think such an approach would have very few possible combinations (given a relatively small card size and a relatively big "finger") and one could easily write a program to generate all possible combinations and break the key in no time. Am i right about this? If so, how could i improve this?
Thanks for your thoughts
UPDATE 1: actually tried it out on iOS. The result is not promising, since the "fingers" get detected differently each time. The distance between them varies significantly (by as much as 40 pixels!). So i guess this is not as easy as i expected, since the OS seems to detect the touch differently each time for the same two circles.
Your question is lacking some relevant information: how far apart need the circles be so that the system can still distinguish them? What resolution can you realistically expect for the circle centers? And by “6mm circle”, do you mean 6mm diameter or radius (or even circumference)?
Lacking details, I'll make some pretty rough approximations. I'll start by requiring that two of the circles will be placed in opposite corners of the card. That way, you can find them by looking for a pair with maximal distance, and from that compute the orientation and size of the card and correct for that. This leaves 7 fingers to be placed randomly. I'll assume 1mm resolution, and restrict myself to a 45×30mm area. Which means 39×24=936 positions per circle, for a total of 9367≈6,3×1020≈269 combinations. OK, this does not exclude overlapping circles. But since the card is still rather sparsely covered, that shouldn't amount to too much. I'd say 64 bit of entropy (i.e. 264 possible combinations) should be reasonable even if you enforce non-overlapping circles. If you can really detect the circle centers with the required resolution, that is. This should be sufficient security for most applications. Far better than 8-letter passwords, but worse than the symmetric keys usually used for e.g. AES.
Since all of this depends very much on the resolution, it might be worthwhile to investigate that aspect first. Usually you'll get pixel coordinates for your finger positions, but it would be expecting too much to assume that you'd always get the pixel coordinate closest to the center of your circle. So you might start by writing a small application which draws a 6mm circle and records coordinates it receives. Then place a 6mm artificial circle in that drawn one a large number of times. Look how far the recorded positions differ from the center of circle. Take the maximum of those differences, perhaps after removing outliers. I'd add a pixel or two to that, to account for rounding errors due to the rotation of the card. Then turn that pixel count back into a metric length. This is the resolution you can expect. You might have to do this for several devices. If you do perform these experiments, let me know what you find and I'll update my answer accordingly.
Let me start out by saying my end goal is something that resembles the image below. It has 36 circles in each of the rings, spaced such that each dot is mid way between two dots in the circle inside of it
I figured out I could use a stroke-dasharray with really small lengths (.001 in my case) and stroke-linecap="round" to make the borders circular dots. The way I have it set up now each circle has a radius 5 bigger than the last and an incremented percentage for the stroke-dasharray. Here is my jsFiddle. Currently My inner most ring only has 21 dots and my outermost ring has 29 dots
How can I get the same number of dots per circle? Is there a mathematical way to do this or an attribute that I am unaware of? What can be done to evenly space out the circles using the whole circumference equally (instead of having some on the right side of the what I perceive as the x-axis)?
It seems to me that I would have to simply guess and check with the values in order to get it the way I want but I would love to be proven wrong. The stroke-dasharray documentation on Mozilla and W3C aren't very useful
Since you're using stroke-dasharray on a circle, you need to use π (3.14159265) to get even spacing.
Given the formula spacing = (radius × 2) × 3.14159265 ÷ numberOfCircles, your SVG circle would be <circle r="{radius}" stroke-dasharray="0.001, {spacing}"/>.
To achieve the spiral effect, apply a rotation of 360 ÷ numberOfCircles ÷ 2 to every other ring. I used CSS to accomplish this, circle:nth-child(even) being the selector and -webkit-transform: rotate( {rotation} ); being the style applied.
I forked your JSFiddle1.
1 Note that the spiral is visible in webkit browsers only. Also, the rings are slightly misaligned on the right for, to my knowledge, unknown reasons.
This question already has answers here:
svg: generate 'outline path'
(2 answers)
Closed 5 years ago.
I want to convert a stroked path to a filled object. (Programmatically, in JavaScript.)
The line is just a simple curved line, a sequence of coordinates. I can render this line as a path, and give it a stroke of a certain thickness... but I'm trying to get a filled shape rather than a stroked line, so that I can do further modifications on it, such as warping it, so the resulting 'stroke' might vary in thickness or have custom bits cut out of it (neither of these things are possible with a real SVG stroke, as far as I can tell).
So I'm trying to manually 'thicken' a line into a solid shape. I can't find any function that does this – I've looked through the docs of D3.js and Raphaël, but no luck. Does anyone know of a library/function that would do this?
Or, even better: if someone could explain to me the geometry theory about how I would do this task manually, by taking the list of line coordinates I have and working out a new path that effectively 'strokes' it, that would be amazing. To put it another way, what does the browser do when you tell it to stroke a path – how does it work out what shape the stroke should be?
There has been a similar question recently:
svg: generate 'outline path'
All in all, this is a non-trivial task. As mentioned in my answer to the linked question, PostScript has a command for generating paths that produce basically the same output as a stroke, called strokepath. If you look at what Ghostscript spits out when you run the code I posted at the linked question, it's pretty ugly. And even Inkscape doesn't really do a good job. I just tried Path => Outline stroke in Inkscape (I think that's what the English captions should say), and what came out didn't really look the same as the stroked path.
The "simplest" case would be if you only have non-self-intersecting polylines, polygons or paths that don't contain curves because in general, you can't draw exact "parallel" Bézier curves to the right and the left of a non-trivial Bézier curve that would delimit the stroked area - it's mathematically non-existent. So you would have to approximate it one way or the other. For straight line segments, the exact solution can be found comparatively easily.
The classic way of rendering vector paths with curves/arcs in them is to approximate everything with a polyline that is sufficiently smooth. De Casteljau's Algorithm is typically used for turning Bézier curves into line segments. (That's also basically what comes out when you use the strokepath command in Ghostscript.) You can then find delimiting parallel line segments, but have to join them correctly, using the appropriate linejoin and miterlimit rules. Of course, don't forget the linecaps.
I thought that self-intersecting paths might be tricky because you might get hollow areas inside the path, i.e. the "crossing area" of a black path might become white. This might not be an issue for open paths when using nonzero winding rule, but I'd be cautious about this. For closed paths, you probably need the two "delimiting" paths to run in opposite orientation. But I'm not sure right now whether this really covers all the potential pitfalls.
Sorry if I cause a lot of confusion with this and maybe am not of much help.
This page has a fairly good tutorial on bezier curves in general with a nice section on offset curves.
http://pomax.github.io/bezierinfo/
A less precise but possibly faster method can be found here.
http://seant23.wordpress.com/2010/11/12/offset-bezier-curves/
There is no mathematical answer, because the curve parallel to a bezier curve is not generally a bezier curve. Most methods have degenerate cases, especially when dealing with a series of curves.
Think of a simple curve as one with no trouble spots. No cusps, no loops, no inflections, and ideally a strictly increasing curvature. Chop up all the starting curves into these simple curves. Find all the offset curves of these simple curves. Put all the offset curves back together dealing with gaps and intersections. Quadratic curves are much more tractable if you have the option to work with them.
I think most browsers do something similar to processingjs, as they have degenerate cases even with quadratic curves. For example, look at the curve 200,300 719,301 500,300 with a thickness of 100 or more.
The standard method is the Tiller-Hanson algorithm (Offsets of Two-Dimensional Profiles, 1984, which irritatingly is not on line for free) which creates a good approximation. The idea is that because the control points of each Bezier curve lie on lines tangent to the start and end of the curve, a parallel curve will have the same property. So we offset the start and the end of the curve, then find new control points using these intersections. However, that gives very bad results for sharp curves, so the first step is to bisect the original curve, which is very easy to do to Bezier curves, until it turns through a sufficiently small angle.
Other refinements are needed to deal with (i) intersections between the parallels, on the inside of each vertex; (ii) inserting an arc of a circle to fill the gap on the outside of each vertex; and (iii) adding end-caps - square, butt or circular.
Tiller-Hanson is difficult to implement, but there's a good open-source implementation in the FreeType library, in ftstroke.c (http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/base/ftstroke.c).
I'm sorry to say that it can be quite difficult to integrate this code, but I have used it successfully, and it works well.
I'm using Löve2D for writing a small game. Löve2D is an open source game engine for Lua. The problem I'm encountering is that some antialias filter is automatically applied to your sprites when you draw it at non-integer positions.
love.graphics.draw( sprite, x, y )
So when x or y is not round (for example, x=100.24), the sprite appears blurred. The same happens when the sprite size is not even, because (x,y) points to the center of the sprite. For example, a sprite which is 31x30 big will appear blurred again, because its pixels are painted in non-integer positions.
Since I am using pixel art, I want to avoid this all the way, otherwise the art is destroyed by this effect. The workaround I am using so far is to force the coordinates to be round by littering the code with calls to math.floor(), and forcing all the sprites to have even sizes by adding a row or column of transparent pixels with the paint program, if needed.
Is there some command to deactivate the antialiasing I can call at program startup?
If you turn off anti-aliasing you will just get aliasing, hence the name! Why are you drawing at non-integral positions, and what do you want it to do about those fractional parts? (Round them to the nearest value? Truncate them? What about if they're negative?)
Personally I would leave the low level graphics alone and alter your code to use accessors for x and y that perform the rounding or truncation that you require. This guarantees your pixel art ends up drawn on integer boundaries while keeping the anti-aliasing on that you might need later.
Another possible work around may be to use math.floor() to round your integers as a cheap workaround.
In case anyone is interested, I've been asking in other places and found out that what I am asking is already requested as feature: http://love2d.org/forum/tracker.php?p=2&t=7
So, the current version of Löve that I'm using (0.5.0) still doesn't allow to disable the antialias filter, but the feature is already in the SVN version of the engine.
you can turn off anti-aliasing by adding love.graphics.setDefaultFilter("nearest", "nearest", 1) to love.load()