Correcting skewed SVG rendering - web

I have created a single jsbin: http://jsbin.com/vokoyisofo/edit?html,css,output
You can see four triangles rendering within one another. Each triangle is 10% smaller than the previous. The containing SVG is 300x300. I would expect everything to render out square but that doesn't happen. I assume there is some sort of screen stretching happening. The space between the bottom borders of each triangle looks much larger than the space between the top tips.
How do I correct for this?

The distance from the top vertex of the outer triangle to the top vertex of the next largest one is 30 units.
The distance from the right hand bottom corner vertex of the outer triangle to the right hand bottom corner vertex of the next largest one is not 30 units. It's √(30 * 30 + 30 * 30) units or approximately 42 units.
That's why the shape is only symmetrical in the vertical axis. It looks skewed because that's how you've defined it.
If you want it to be symmetrical you want the bottom vertices to go in by 30 units in the direction of the centre of the triangle which will mean that they decrease by 30 / √2 units in each of x and y

Related

What is the endpoint calculation in the Xiaolin Wu algorithm doing?

The Xiaolin Wu algorithm draws an anti-aliased line between two points. The points can be at sub-pixel, i.e. non-integer coordinates. I'll assume the reader is familiar with the algorithm and just recall the important features. We loop across the major (longer) axis of the line, let's say it's the x-axis, basically proceeding column-by-column. In each column we color two pixels. The computation is equivalent to this: place a 1x1 square centered on the line, at the point whose x coordinate is the center of the the given column of pixels. Let's call it S. If we think of each pixel as a 1x1 square in the plane, we now calculate the area of intersection between S and each of the two pixels it straddles, and use those areas as the intensities with which to color each pixel.
That's nice and clear, but what is going on with the calculations for the endpoints? Because the endpoints can be at non-integer positions, they have to be treated as a special case. Here's the pseudocode from the linked Wikipedia article for handling the first endpoint x0, y0:
// handle first endpoint
xend := round(x0)
yend := y0 + gradient * (xend - x0)
xgap := rfpart(x0 + 0.5)
xpxl1 := xend // this will be used in the main loop
ypxl1 := ipart(yend)
plot(ypxl1, xpxl1, rfpart(yend) * xgap)
plot(ypxl1+1, xpxl1, fpart(yend) * xgap)
I edited out the if (steep) condition, so this is the code for the case when the slope of the line is less than 1. rfpart is 1-fpart, and fpart is the fractional part. ipart is the integer part.
I just have no idea what this calculation is supposed to be doing, and I can't find any explanations online. I can see that yend is the y-coordinate of the line above xend, and xend is the x coordinate of the pixel that the starting point (x0, y0) is inside of. Why are we even bothering to calculate yend? It's as if we're extending the line until the nearest integer x-coordinate.
I realize that we're coloring both the pixel that the endpoint is in, and the pixel either immediately above or below it, using certain intensities. I just don't understand the logic behind where those intensities come from.
With the Xiaolin Wu algorithm (and sub-pixel rendering techniques in general) we imagine that the screen is a continuous geometric plane, and each pixel is a 1x1 square region of that plane. We identify the centers of the pixels as being the points with integer coordinates.
First, we find the so-called "major axis" of the line, the axis along which the line is longest. Let's say that it's the x axis. We now loop across each one-pixel-wide column that the line passes through. For each column, we find the point on the line which is at the center of that column, i.e. such that the x-axis is an integer. We imagine there's a 1x1 square centered at that point. That square will completely fill the width of that column and will overlap two different pixels. We color each of those pixels according to the area of the overlap between the square and the pixel.
For the endpoints, we do things slightly differently: we still draw a square centered at the place where the line crosses the centerline of the column, but we cut that square off in the horizontal direction at the endpoint of the line. This is illustrated below.
This is a zoomed-in view of four pixels. The black crosses represent the centers of those pixels, and the red line is the line we want to draw. The red circle (x0, y0) is the starting point for the line, the line should extend from that point off to the right.
You can see the grey squares centered on the red crosses. Each pixel is going to be colored according to the area of overlap with those squares. However, in the left-hand column, we cut-off the square at x-coordinate x0. In light grey you can see the entire square, but only the part in dark grey is used for the area calculation. There are probably other ways we could have handled the endpoints, for instance we could have shifted the dark grey region up a bit so it's vertically centered at the y-coordinate y0. Presumably it doesn't make much visible difference, and this is computationally efficient.
I've annotated the drawing using the names of variables from the pseudocode on Wikipedia.
The algorithm is approximate at endpoints. This is justified because exact computation would be fairly complex (and depend on the type of endpoint), for a result barely perceivable. What matters is aliasing along the segment.

Find the largest square that can fit within a given polygon centered a a given point

Let's say I have a polygon specified by a set of vertices.
In addition, I also have a defined "starting point" that could be anywhere in the polygon.
How could I find the largest square, centered at the starting point, that fits completely within the polygon?
How about finding the largest x,y aligned distances from vertices to the start point?
If you also consider the sign of the distance you get the maximun +x,-x size and +y,-y size
The size of the square is limited by either one of its sides hitting a vertex of the polygon or one of its corners hitting a side of the polygon.
If rotation is not allowed,
find the shortest horizontal or vertical distance from the target point to the vertices;
find the closest intersections of the main bissectors through the target point and the polygon outline.
Keep the smallest square so defined.
If rotation is allowed, the problem is more difficult.

fast calculation of the intersection area of a triangle and the unit square

In my current project I need to calculate the intersection area of triangles and the unit squares in an infinite grid.
For every triangle (given by three pairs of floating point numbers) I need to know the area (in the interval (0,1]) it has in common with every square it intersects.
Right now I convert both (the triangle and the square) to polygons and use Sutherland-Hodgman polygon clipping to calculate the intersection polygon, which I then use to calculate its area.
This approach now shows to be a performance bottleneck in my application. I guess a more specialized (analytical) algorithm would be much faster. Is there a standard solution for this problem, or do you have any idea? I only need the areas, not the shape of the intersections.
Your polygon are convex. There are some algorithms for convex polygons faster than general ones. I've used O'Rourke algorithm with success (code from his book here, I believe that good description exists). Note that some values may be precomputed for your squares.
If your polygons not always intersect, then you may at first check the fact of intersection with separating axes method.
Another option to try- Liang-Barski algorithm for clipping every triangle edge by square.
Edit: You can quickly find all intersections of triangle edges with grid using algorthm of Amanatides and Woo (example in grid traversal section here)
To process this task with hi performance , i suggest some modifications of
Vatti line sweep clipping.
http://en.wikipedia.org/wiki/Vatti_clipping_algorithm
Stepping from minimal Y vertex of your Triangle make such steps:
sort vertexes by Y coordinate
step Y higher to MIN(nextVertex.Y, nextGridBottom)
Calculate points of intersection of grid with edges.
Collect current trapezoid
repeat from step2 until vertex with highest Y coordinate.
Split trapezoids by X coordinate if required.
here is example of Trapezoidalization in X direction
http://www.personal.kent.edu/~rmuhamma/Compgeometry/MyCG/PolyPart/polyPartition.htm
It illustrate main idea of line sweep algorithm. Good luck.
You are not mentioning what precision you are looking for. In case you are looking for a analytical method, disregard this answer, but if you just want to do antialiasing I suggest a scanline edge-flag algorithm by Kiia Kallio. I have used it a few times and it is quite fast and can be set up for very high precision. I have a java implementation if you are interested.
You can take advantage of the regular pattern of squares.
I'm assuming the reason this is a bottleneck is because you have to wait while your algorithm finds all squares intersecting any of the triangles and computes all the areas of intersection. So we'll compute all the areas, but in batches for each triangle in order to get the most information from the fewest calculations.
First, as explained by others, for each edge of the triangle, you can find the sequence of squares that edge passes through, as well as the points at which it crosses each vertical or horizontal edge of a square.
Do this for all three sides, keeping a list of all the squares you encounter, but keep only one copy of each square. It may be useful to store the squares in multiple lists, so that all squares on a given row are all kept in the same list.
When you've found all squares the triangle's edges pass through, if two of those squares were on the same row, any squares between those two that are not in the list are completely inside the triangle, so 100% of each of those squares is covered.
For the other squares, the calculation of area can depend on how many vertices of the triangle are in the square (0, 1, 2, or 3) and where the edges of the triangle intersect the sides of the square. You can summarize all the cases in a few pencil-and-paper drawings, and come up with calculations for each one. For example, when an edge of triangle crosses two sides of the square, with one corner of the square on the "outside" side of the edge, that corner is one angle of a small triangle "cut off" by that edge of the larger triangle; use the points of intersection on the square's sides to compute the area of the small triangle and deduct it from the area of the square. If two points instead of one are "outside", you have a trapezoid whose two base lengths are found from the points of intersection, and whose height is the width of the square; deduct its area from the square. If three points are outside, deduct the entire area of the square and then add the area of the small triangle.
One vertex of the large triangle inside the square, three corners of the square outside that angle: draw a line from the remaining corner to the triangle's vertex, so you have two small triangles, deduct the entire square and add those triangles' areas. Two corners of the square outside the angle, draw lines to the vertex to get three small triangles, etc.
I'm phrasing this so that you always assume you start with the entire area of the square and reduce the area by some amount depending on how the edge of the triangle intersects the square. That way, in the case where the edges of the triangle intersect the square more than twice--such as one edge cuts across one corner of the square and another edge cuts across a different corner, you can just deduct the area cut off by the first edge, then deduct the area cut off by the second edge.
This will be a considerable number of special cases, though you can take advantage of symmetry; for example, you don't have to write the complete calculation for "cut off a triangle in one corner" four times.
You'll write a lot more code than if you just took someone's convex-polygon library off the shelf, and you will want to test the living daylights out of it to make sure you didn't forget to code any cases, but once you get it working, it shouldn't take much more effort to make it reasonably fast.

Gaps Between Rectangles Connected at the Center

I'm experimenting with a vector based graphics style with objects represented as series of line segments with a given width(it would probably be easier to think of these as rectangles). The problem is that these segments are connected at the center and leave a gap (shown below). I've determined that the most efficient way to cover this gap is simply to cover it with a triangle, and since I'm working in OpenGL, all I need are the points of the two points that don't overlap with the other rectangle, the third point being the center point where the two line segments(rectangles) are connected. How can I determine which points I need to use for the triangle, given that I have all of the points from both rectangles?
EDIT: I will also accept alternative solutions, as long as they cover up that gap.
EDIT 2: Nevermind, I solved it. I'll post code once I have better Internet connection.
Maybe I'm misunderstanding the question... but if you zoom in on the top corner of your red pentagon, you get something like this, am I right?
where A and B are nodes on the rectangle for edge1 and C and D are nodes on the rectangle for edge2. You say you already know these coordinates. And from what you say, the edges meet at the centre, which is halfway between A and B, and also halfway between C and D. So call this point X, and you can calculate its coordinates easily I guess.
So all you need to do is draw the missing triangle AXC, right? So one way would be to determine that A and C are on the "outside" of the polygon (and therefore need filling) and B and D are on the "inside" and therefore don't. But it's probably easier to just draw both, as it doesn't hurt. So if you fill AXC and BXD, you'd get this:
The solution I found assumes that there are 3 basic cases:
First, the three unique center points for the two rectangle proceed upward (positive y direction) so the gap is either on the left or right of the connection. In my code, I had the corner points of the rectangle organized by their orientation to the left or right of the center point, so if the bottom rectangle's left point is below the top rectangle's left point, then the gap is between the left points of the two rectangles, otherwise the gap is between the right points.
Second, the three unique center points have a maximum at the center most of the center points, so the gap is on the top. The gap is then between the two points with the maximum y values.
Third, the three unique center points have a minimum at the center most of the center points, so the gap is on the bottom. The gap is then between the two points with the minimum y values.
[I'll post pictures of the example cases if it is requested]

How to find line segments intersecting a 2D viewport

In an infinite 2D space there are a set of lines, each line having a start and end point, and a time of creation: Line(p0, p1, t).
I want to find the lines that should be rendered in a top-down view of this 2D space (higher values of t show up closer to the viewport, not that it should be relevant.)
The intuitive answer is "check if either point is within the viewport coordinates," but this falls down when the points are further apart than the viewport area covers.
The other idea I had was using something like geohash, this would limit precision i.e. maximum zoom level of the viewport. The idea is enumerating the hashes of the cells intersected and storing them. This way querying is a matter of asking the right question.
Are there any ideal solutions? Has this been solved before?
I think you need to check two conditions: one that the rectangle of viewport overlaps the rectangle with corners (p0,p1) and the second that some corners of viewport rectangle are on the different sides of the whole line which contains line segment (p0,p1).
The task of finding rectangle overlap can be solved very effectively for very large number of rectangles using R-trees (http://en.wikipedia.org/wiki/R-tree).
The second task can be reduced to checking signs of the cross product of (p1-p0) x (corner_coordinate-p0)
(all three quantities taken as 3-d vectors with third coordinate equal to zero, the result will be vector along the perpendicular direction). There should be corners with the opposite sign of this cross product.

Resources