Below is an svg path (the points) which, when given a thickness, displays the grey shape. I have an svg with the outline of the grey shape, and I would like to generate an approximation (I'm assuming the original is impossible to get back) of the original path. Ideally it would work with shapes that intersect, like a lowercase 'e'.
The opposite of this: svg: generate 'outline path'
This is a bit beyond the scope of a SO answer. However there is plenty of information out there on the web. Converting a bitmap to vectors is called "vectorization". The class of algorithms that attempts to get the "skeleton" of the shape is known as "thinning". Google those three terms.
Most of these algorithms are designed to work with bitmaps, but they should be a useful starting point for your situation.
Related
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 would like to identify the center of an SVG, so that I can manipulate multiple SVGs with ease.
I am trying to make multiple examples of the basic polygons (3 to 8 sides), and quickly realized that I either hade to make my own, which involves a lot of math, or I could pull from wikipedia the current ones. The problem with the former is that it takes a lot of time to translate the coordinates from Sketchup. The problem with the latter is that they are oriented differently and of different size.
I know that you can transform, scale, and rotate the SVG, but I need to know the coordinates of the center of the SVG. How do I find this out, so I can set universal manipulations?
Take the transform="rotate(degrees x y)", I need to know the center to accomplish this.
JS Fiddle
Here, I would like to set all the centers to the same, and then scale them to the same height and width, and potentially rotate them individually so that they all have a flat bottom, not a vertex.
The generic answer to your question isn't obvious...
It might be simpler for polygons, particularly convex polygons: you can iterate on the path and find its bounding box by computing the max and min of the x and y coordinates of each point of the path.
Then you can decide that the center of the shape is the center of the of the bounding box.
An alternative is to put an invisible element at what you estimate to be the center (for complex shapes, the concept of "center" can be variable), and get its coordinates to find out where the center is. Particularly for rotating purpose: you might want to do this rotation around a specific point which might not be the geometrical center.
I need to write some code (for a web.py webapp with a straight-HTML/JS client) that will generate a visual representation of a set of point-values. Each point has an X and Y coordinate, and the value is an integer. If I can use SVG to do this, then I can scale the image client-side with no extra code. Can I actually do this? I am concerned about a couple of things:
The points don't necessarily have any relation to each other. They aren't necessarily in a grid, nor can we say how many points are nearby, etc.
Gradients are primarily one-direction, and multiple gradients on the same shape seems to be a foreign concept.
Fills require an existing image, at which point, I'd be better off generating the entire image server-side anyway.
Objects always have a layering, even if it isn't specified, which can change how the image is rendered.
If it helps, consider a situation where we have a point surrounded by 5 others, where one of them is a bit closer than the others (exact distances and sizes can be adjusted). All six of the points have different colors (Red, Green, Blue, Cyan, Magenta, Yellow, with red in the center and Yellow being slightly closer), and the outer five points are arranged roughly in a pentagon. Note that this situation is not the only option, just a theoretically possible situation.
Can I do this with SVG, or should I render an image server-side?
EDIT: The main difficulty isn't in drawing the points, it is in filling the space between the points so that there is no whitespace, and color transitions aren't harsh/unpredictable if you know the data.
I don't entirely understand the different issues you are having with wanting to use svg. I am currently using the set up you are describing to render X-Y scatter plots and gaussian curves and found that it works great.
Regarding the last point about object layering, you have to be particularly careful when layering objects with less than 100% opacity which are different colors. The way the colors "add" depends on the order in which you add the objects to your svg drawing.
Thankfully you can use different filters to overlay the colors without blending them. Specifically I am using the FeComposite filter element. There is a good example of its usage here:
http://www.w3.org/TR/SVG/filters.html#feCompositeElement
I would like to do some odd geometric/odd shape recognition. But I'm not sure how to do it.
Here's what I have so far:
Convert RGB image to Monochrome.
Otsu Threshold
Hough Transform.
I'm not sure what to do next.
For geometric information, you could do a raster to vector conversion to convert your image into coordinated vectors (lines and points) and finite element analysis to look for known shapes. Not easy but libraries should be available for both.
Edit: Note that there are sometimes easier practical solutions, but they depend on the image and types of errors. For example, removing perspective, identifying a 3d object from a 2d image, significance of colour, etc... You often see registration markers added to the real world object to overcome
this and allow much easier identification. Looking up articles on feature extraction techniques might help.
I'm suprised that Google doesn't shed much light on this.
I'm creating a simple CAD viewer using Direct3D. Because of it's nature (zoom functionality etc) text elements must be vector text; I can't use textured polys.
I've called into gdi32.dll to get the glyphs and create quite reasonable text outlines from straight lines and bezier curves, however the text isn't solid and the points aren't necessarily regular in any way. Enclosing characters (b, p, o, A, etc) actually have more than one seperate outline.
As a consequence, I can't just shoot the points into a vertex buffer and specify a primitive type.
All I can do at the moment is render the outlines as line strips, resulting in hallow text.
Can anyone suggest a good strategy for rendering solid vector text with their outlines?
Note that I interpolate the bezier curves into point lists (A lot of people use shaders/witchcraft).
You don't mention what version of DirectX you are using, but the utility function D3DXCreateText will create a 3D mesh for a given text in any TrueType font. If you want a 2D version, simply use no or minimal extrusion, and straight-on orthogonal projection.
If you need explicit outlines, you might be able to either (a) combine this approach with the Outline you already have, (b) draw the text twice at a slightly different scale (depending on current zoom level) or (c) use shaders to draw a pixel-perfect outline.
A screenshot of the exact look-and-feel you are after might help. My CAD drawings all have solid text, no outlines.
I am creating text meshes with D3DXCreateText (Win32, DX9). They rotate nicely. However, they always seem to be the same size regardless of the height of the font that has been selected in the DC.
The mesh lines in smaller characters are aliased and don't look good on video cards without multisampling.