As far as I can tell, there isn't a great answer to this problem, but hoping someone out there might be able to provide some guidance. Polygons rendering in canvas or SVG are fine, but the more granular the data, the more dismal the performance gets. This is especially true when a spline-basis algorithm is applied to polygon to create the illusion of a 'smooth' polygon. A smooth polygon is technically impossible because they are simply lines, so all you can do is add more points to create the this illusion.
Does anyone know of a way to take a polygon and convert it to bezier curves using a spline basis algorithm?
Edit:
Essentially I'm looking for what this Corona SDK is doing in this video:
Take a large amount of straight points and converting them to fewer curve points creating a smooth look of the original path (and less data).
https://www.youtube.com/watch?v=v63NAzQE7Bw
Related
I am new to the WebGL and shaders world, and I was wondering what the best way for me to paint only the pixels within a path. I have the positions 2d of each point and I would like to fill with a color inside the path.
2D Positions
Fill
Could someone give me a direction? Thanks!
Unlike the canvas 2d API to do this in WebGL requires you to triangulate the path. WebGL only draws points (squares), lines, and triangles. Everything else (circles, paths, 3d models) is up to you to creatively use those 3 primitives.
In your case you need turn your path into a set of triangles. There are tons of algorithms to do that. Each one has tradeoffs, some only handle convex paths, some don't handle holes, some add more points in the middle and some don't. Some are faster than others. There are also libraries that do it like this one for example
It's kind of a big topic arguably too big to go into detail here. Other SO questions about it already have answers.
Once you do have the path turned into triangles then it's pretty straightforward to pass those triangles into WebGL and have them drawn.
Plenty of answers on SO already cover that as well. Examples
Drawing parametric shapes in webGL (without three.js)
Or you might prefer some tutorials
There is a simple triangulation (mesh generation) for your case. First sort all your vertices into CCW order. Then calculate the middle point of all vertices. Then iterate over your sorted vertices, and push a triangle made of the middle point, the point at vertices[index] and the point at vertices[index+1] to the mesh.
I've been scouring the internet for days, but have been unable to find a good answer (or at least one that made sense to me) to what seems like it should be a common question. How does one scale an arbitrary polygon? In particular, concave polygons. I need an algorithm which can handle concave (definitely) and self-intersecting (if possible) polygons. The obvious and simple algorithm I've been using to handle simple convex polygons is calculating the centroid of the polygon, translating that centroid to the origin, scaling all the vertices, and translating the polygon back to its original location.
This approach does not work for many (or maybe all) concave polygons as the centroid often falls outside the polygon, so the scaling operation also results in a translation and I need to be able to scale the polygon "in place" without the final result being translated.
Is anybody aware of a method for scaling concave polygons? Or maybe a way of finding the "visual center" which can be used as a frame of reference for the scaling operation?
Just to clarify, I'm working in 2D space and I would like to scale my polygons using the "visual center" as the frame of reference. So maybe another way to ask the question would be, how do I find the visual center of a concave and/or self-intersecting polygon?
Thanks!
I'm not sure what your problem is.
You're working in an affine space, and you're looking for an affine transformation to scale your polygon ?
If i'm right, just write the transformation matrix:
scaling matrix
homotethy
And transform your polygon with matrix
You can look up for affine transformation matrix.
hope it helps
EDIT
if you want to keep the same "center", you can just do an homotethy of parameter lambda with center G = barycenter of the polygon:
it verifies :
G won't move since it's the center of the homotethy.
It will still verify the relation below, so it will still be the barycenter. (you just multiply the relation by lambda)
in your case G is easy to determinate: G(x,y) : (average of x values of points, average of y values of points)
and it should do what you need
Perhaps Craig is looking for a "polygon offset" algorithm - where each edge in the polygon is offset by a given value. For example, given a clockwise oriented polygon, offsetting edges towards the left will increase the size of the polygon. If this is what Craig is looking for then this has been asked and answered before here - An algorithm for inflating/deflating (offsetting, buffering) polygons.
If you're looking for a ready made (opensource freeware) solution, I've also created a clipping library (Clipper) written in Delphi, C++ and C# which includes a rather simple polygon offsetting function.
The reason why you can't find a good answer is because you are being imprecise with your requirements. First explicitly define what you mean by "in-place". What is being kept constant?
Once you have figured that out, then translate the constant point to the origin, scale the polygon as usual, and translate back.
I've been searching far and wide on the seven internets, and have come to no avail. The closest to what I need seems to be The cutting stock problem, only in 2D (which is disappointing since Wikipedia doesn't provide any directions on how to solve that one). Another look-alike problem would be UV unwrapping. There are solutions there, but only those that you get from add-ons on various 3D software.
Cutting the long talk short - what I want is this: given a rectangle of known width and height, I have to find out how many shapes (polygons) of known sizes (which may be rotated at will) may I fit inside that rectangle.
For example, I could choose a T-shaped piece and in the same rectangle I could pack it both in an efficient way, resulting in 4 shapes per rectangle
as well as tiling them based on their bounding boxes, case in which I could only fit 3
But of course, this is only an example... and I don't think it would be much use to solving on this particular case. The only approaches I can think of right now are either like backtracking in their complexity or solve only particular cases of this problem. So... any ideas?
Anybody up for a game of Tetris (a subset of your problem)?
This is known as the packing problem. Without knowing what kind of shapes you are likely to face ahead of time, it can be very difficult if not impossible to come up with an algorithm that will give you the best answer. More than likely unless your polygons are "nice" polygons (circles, squares, equilateral triangles, etc.) you will probably have to settle for a heuristic that gives you the approximate best solution most of the time.
One general heuristic (though far from optimal depending on the shape of the input polygon) would be to simplify the problem by drawing a rectangle around the polygon so that the rectangle would be just big enough to cover the polygon. (As an example in the diagram below we draw a red rectangle around a blue polygon.)
Once we have done this, we can then take that rectangle and try to fit as many of that rectangle into the large rectangle as possible. This simplfies the problem into a rectangle packing problem which is easier to solve and wrap your head around. An example of an algorithm for this is at the following link:
An Effective Recursive Partitioning Approach for the Packing of Identical Rectangles in a Rectangle.
Now obviously this heuristic is not optimal when the polygon in question is not close to being the same shape as a rectangle, but it does give you a minimum baseline to work with especially if you don't have much knowledge of what your polygon will look like (or there is high variance in what the polygon will look like). Using this algorithm, it would fill up a large rectangle like so:
Here is the same image without the intermediate rectangles:
For the case of these T-shaped polygons, the heuristic is not the best it could be (in fact it may be almost a worst case scenario for this proposed approximation), but it would work very well for other types of polygons.
consider what the other answer said by placing the t's into a square, but instead of just leaving it as a square set the shapes up in a list. Then use True and False to fill the nested list as the shape i.e. [[True,True,True],[False,True,False]] for your T shape. Then use a function to place the shapes on the grid. To optimize the results, create a tracker which will pay attention to how many false in a new shape overlap with trues that are already on the grid from previous shapes. The function will place the shape in the place with the most overlaps. There will have to be modifications to create higher and higher optimizations, but that is the general premise which you are looking for.
Starting with a 3D mesh, how would you give a rounded appearance to the edges and corners between the polygons of that mesh?
Without wishing to discourage other approaches, here's how I'm currently approaching the problem:
Given the mesh for a regular polyhedron, I can give the mesh's edges a rounded appearance by scaling each polygon along its plane and connecting the edges using cylinder segments such that each cylinder is tangent to each polygon where it meets that polygon.
Here's an example involving a cube:
Here's the cube after scaling its polygons:
Here's the cube after connecting the polygons' edges using cylinders:
What I'm having trouble with is figuring out how to deal with the corners between polygons, especially in cases where more than three edges meet at each corner. I'd also like an algorithm that works for all closed polyhedra instead of just those that are regular.
I post this as an answer because I can't put images into comments.
Sattle point
Here's an image of two brothers camping:
They placed their simple tents right beside each other in the middle of a steep walley (that's one bad place for tents, but thats not the point), so one end of each tent points upwards. At the point where the four squares meet you have a sattle point. The two edges on top of each tent can be rounded normally as well as the two downward edges. But at the sattle point you have different curvature in both directions and therefore its not possible to use a sphere. This rules out Svante's solution.
Selfintersection
The following image shows some 3D polygons if viewed from the side. Its some sharp thing with a hole drilled into it from the other side. The left image shows it before, the right after rounding.
.
The mass thats get removed from the sharp edge containts the end of the drill hole.
There is someething else to see here. The drill holes sides might be very large polygons (lets say it's not a hole but a slit). Still you only get small radii at the top. you can't just scale your polygons, you have to take into account the neighboring polygon.
Convexity
You say you're only removing mass, this is only true if your geometry is convex. Look at the image you posted. But now assume that the viewer is inside the volume. The radii turn away from you and therefore add mass.
NURBS
I'm not a nurbs specialist my self. But the constraints would look something like this:
The corners of the nurbs patch must be at the same position as the corners of the scaled-down polygons. The normal vectors of the nurb surface at the corners must be equal to the normal of the polygon. This should be sufficent to gurarantee that the nurb edge will be a straight line following the polygon edge. The normals also ensure that no visible edges will result at the border between polygon and nurbs patch.
I'd just do the math myself. nurbs are just polygons. You'll have some unknown coefficients and your constraints. This gives you a system of equations (often linear) that you can solve.
Is there any upper bound on the number of faces, that meet at that corner?
You might you might employ concepts from CAGD, especially Non-Uniform Rational B-Splines (NURBS) might be of interest for you.
Your current approach - glueing some fixed geometrical primitives might be too inflexible to solve the problem. NURBS require some mathematical work to get used to, but might be more suitable for your needs.
Extrapolating your cylinder-edge approach, the corners should be spheres, resp. sphere segments, that have the same radius as the cylinders meeting there and the centre at the intersection of the cylinders' axes.
Here we have a single C++ header for generating triangulated rounded 3D boxes. The code is in C++ but also easy to transplant to other coding languages. Also it's easy to be modified for other primitives like quads.
https://github.com/nepluno/RoundCornerBox
As #Raymond suggests, I also think that the nepluno repo provides a very good implementation to solve this issue; efficient and simple.
To complete his answer, I just wrote a solution to this issue in JS, based on the BabylonJS 3D engine. This solution can be found here, and can be quite easily replaced by another 3D engine:
https://playground.babylonjs.com/#AY7B23
I need to plot the transformation of a 3d object against time. I have the 3d shapes for each moment in time, but they are not guaranteed to be geometrically well placed, so I cannot just render them and slap the pictures together into a movie. I therefore need to align them so that they are pleasantly and consistently oriented with respect to the camera.
What I would do is to take pairs of 3d objects, center them with respect to the geometric center, then perform the proper rotation around some axis so to minimize the RMSD among the points. That's not hard, but I'd enjoy to know if there's something ready out there so not to reinvent the math (and the code). Of course, I'd also accept objections to my method.
I'm working in python, but any code will do, and I will convert it.
The Kabsch algorithm does that. See: http://en.wikipedia.org/wiki/Kabsch_algorithm.
It appears that what I need is the Kabsch algorithm.