Calculate area of split polygon - algorithm

I need to split a polygon with a line, similar to this: How can I split a Polygon by a Line?, but I don't actually care about the resulting polygons, I just want to know the area on each side of the line.
I know I can just do the split and calculate the area of each resulting part, but I was wondering if there is any more efficient algorithm if I just need the area.
For instance, in the image below, the yellow shape shows an original polygon and the line across it shows how I want to split it. Notice that the split line always goes between to vertices, but does not necessarily cross the entire polygon. (Note: the fact that the cut line seems to pass through a third vertex is just an accident: this may be the case but is not necessarily so).
The red and green shapes show the resulting splits, and all I'm interested in is the total area of the red polygons (or of the green, either way)

If you can determine the intersection points of the split then you can calculate the area of the first one and subtract it from the total area to determine the area of the second one.

Related

Dividing a 2D plane into areas that belong together

I have multiple polygons where some are of different color and some of equal color. I want to group them into areas (e.g. new polygons) that completely contain all polygons of the same color.
See the two simple examples which would both satisfy these conditions. The dotted red lines are the desired result.
The first example divides the whole plane, the second does not. I don't care as long as all polygons of same color are grouped.
It can be assumed that a solution exists, i.e. there will not be a polygon of blue color fully enclosed by one of black color. Also polygons do not intersect but may share a border like in the example. However, edge cases like this could occur:
I'm looking for an algorithm that can accomplish this. The first example reminded my of Voronoi diagrams, but it's different because I have polygons not individual points.
A real world example of this would be to divide a city into districts base on housing blocks.
What I ended up doing is to apply these steps iteratively:
Use a buffer algorithm to grow all polygons.
Combine the ones of equal color with a union operation.
Iterate all resulting shapes and substract all other shapes from them, in order to get rid of overlapping areas. This iteration must be done alternatingly from the start and the end, otherwise the shapes will grow unevenly.
These steps are repeated until the result looks visually pleasing. This procedure does not handle the special case mentioned in the second picture of the question (it will isolate the two blue polygons), but it was in the end an acceptable compromise for my use case.

How to smoothen a jagged border of an image into a straight line?

I have an image like this (thresholding, noise removal, etc. completed):
My final output should be an image without any of the jagged edges, and smaller than the given image. By this, I mean to say that the only difference between the 2 images must be that in the new one, the jagged edges must be removed, and not the jagged edges filled in. Like so (the final image must be the region within the red border, the red border is shown only for explanation):
I was thinking of something along the lines of using Hough transforms, or of using dilations and then erosions, but nothing seems to be working (probably my fault, because I have not worked in too much detail with them before).
Note that the language I'd like t do this in is MATLAB.
There are 2 primary aims to this:
To get the edges themselves, using Hough transforms
So that the 'Extrema' property returns the desired pints when using regionprops, like so:
The question, in a more concise form:
How would I go about extracting this T in MATLAB, such that it does not have rugged edges, but the overall figure is not larger than the original, as shown in the second figure above? In other words, what set of transformations (in MATLAB) would I use to smoothen the borders of the image with as little of the area lost as little as possible (but no area added) such that ruggedness disappears?
Is there a more efficient way of extracting the corner (extrema) points as shown in figure 2 above without requiring to go through step 1?
EDIT:
A few more sample images:
NB: All images in consideration will be composed of rectangles approximately at 90 to each other, and no other figure. So smoothening an image with a curved edge, for example, would be beyond the scope of an answer to this question (or even, for that matter, a trapezium, although I think that smoothening 2 straight edges should be the same, irrespective of whether the edge has another parallel to it or not).
Here are a few more images, for reference:
I'm not sure if my answer would satisfy your requirements. I'm putting it here because I think it's too long for a comment.
since you want the final output to be smaller than the input image, erode the input image. You can pick an appropriate kernel size.
perform a corner detection on this eroded image. This will give you all strong corners, but without any order
trace the boundaries of the eroded image. This should give you an ordered list of boundary pixels
now, with the help of these ordered boundary points you can order the corners that you found earlier
filter corner points that form approximately 90 degrees of angle. You can do this considering each 3 ordered corner points (two green points and the red point in between in the image below. It's just for illustration, not corner points that I calculated. At the end of this operation, you have all red points in the image below which are at strong corners, in addition to other yellow and green corner points)
now you can either find the equation of the line connecting 2 consecutive red points
or
fit a least-squares-line to the points between (and including) each 2 consecutive red points
since you did all this processing on a eroded image that is essentially smaller than the original image, you should get a smaller shape

Algorithm for finding empty areas

does anybody know of a good algorithm for this task:
a multi polygon contains the reserved areas
find an empty position for the given polygon which is closest to its original position but does not intersect the reserved areas
I have implemented some very basic algorithm which does the job but far from optimally.
Thank You!
Edit:
my solution basically does the following:
move given polygon in all possible directions dx and dy
check wether the new intersection is less than the previous intersection
if so, use new position and make sure that you don't move your polygon back and forth at the same position
repeat these steps a maximum of N times
Example: it is intended for placing text which should not overlap with each other.
One method that immediately pops into my mind is to shoot a ray (i.e. measure a line segment) from the original position to every vertex of the polygon. Do a comparison on those distances, and then based on those comparisons, narrow it down to the minimally far away line segment of the polygon. Compute the perpendicular intersection of that line with the origin, and you'll get the minimally far away point. If the vertex comparisons don't lead you down the right path, just shoot off lines in random directions, and just stop when you're happy with the result. It doesn't sound like you require optimality.
Let's look at the original problem: making sure that one piece of text doesn't overlap another. Presumably this is for labelling a map. The way I do it is this: draw the text invisibly, checking for overlap (by using a specialised graphics context that instead of drawing a pixel, checks whether a pixel is already there) then try another position along the line on which the text is to be placed - usually a street. I try the middle of the line first, then successive positions further and further left and right of the middle. If that fails I try again with a condensed (narrower) font.

How to erase an area delimited by a line segment and a block of colors?

Given the picture below:
The position of A and B is known, the rest of the picture is just raw pixel data (only red and white pixels). What algorithm can I use to erase the part to the right of AB?
Having two points define a line. The equation of line separates pixels that have to be removed. If you want to delete points in a way that new border is smoothly following the curve of the shape you need some way to interpolate the shape border (based on the information of other points from the border). This interpolation have to pass trough two black points. Now, if you have interpolation you can calculate the interpolation curve between two black points and set to white all points right from the curve. I can suggest to use at least one more point from the curve and use some cubic spline interpolation.
EDIT:
Based on you comment.
Then the algorithm is simple: Keep a pointer that starts from lower point (A) and moves along the border (A') until it reaches the other point. This can be done by checking the neighbors of current pointer location and comparing colors. Now, when you pointer moves remove the line of red points from pointer (A') to line (blue) defined between to points A-B (in green). There is a pointer position when the row is the same as the other black point (e.g A' and B are on the same row). Then start a new pointer from B point in the same way tracing the border and remove the red pixels between two pointers A' and B'.
You need to draw the line from A to B and then start a flood fill on one of the red pixels to the right of the line.

Determining a mean camber line

Fellow programmers,
I know this is a little outside your juridistiction, but I was wondering perhaps if you have time, if you could help me with one "procedure". Not in view of math but what would be the best way to take.
This is an airfoil / profile. Usually, profiles are defined with two sets of data. One is the position of mean camber line, given in the form of x,y where x is usually given in percentages of chord length. Second set of data is thickness at percentages of chord length. Thickness is always drawn perpendicular to the camber line(!), and that gives the profile points.
Now, I have a reverse problem - I have points of a profile, and I need to determine the position of the camber line. Method of interpolation through points can vary, but it doesn't matter, since I can always interpolate as many points as I need, so it comes to linear in the end.
Remember, since the thinkness is drawn perpendicular to the camber line, the position of camber line is not mean between the points of upper and lower line of profile (called the back and face of profile).
Edit (how this is done on paper): Uhh, painfully and in large scale (I'm talking long A0 paper here, that is 1189x5945mm on a large drawing desk. You start by drawing a first camber line (CL) iteration through the midpoints (mean points) between the points of face and back at same x ordinates. After that you draw a lot of perpendicular lines, perpendicular to that CL, and find their midpoints between face and back (those points on face and back will no longer have same x values). Connect those, and that is your second iteration CL. After that you just repeat the second step of the procedure by drawing perpendicular lines onto that 2nd CL ... (it usually converges after 3 or 4 iterations).
2nd Edit: Replaced the picture with one which better shows how the thinkness is "drawn" onto the camber line (CL). Another way of presenting it, would be like picture no.2. If you drew a lot of circles, whoce center points are at the camber line, and whose radiuses were the amounts of thickness, then tangents to those circles would be the lines (would make up the curve) of the profile.
The camber line is not the mean line (mean between the points of face and back); it can coincide with it (therefore usually the confusion). That difference is easily seen in more cambered profiles (more bent ones).
3rd edit - to illustrate the difference dramatically (sorry it took me this long to draw it) between the mean line and camber line, here is the process of how it is usually done "on paper". This is a rather deformed profile, for the reason, that the difference between the two can be more easily shown (although profiles like this exist also).
In this picture the mean line is shown - it is a line formed by the mean values of face and back on the same x coordinates.
In this picture onto the mean line, perpendicular lines were drawn (green ones). Midpoints of those perpendicular lines make up for the 1st iteration of the camber line (red intermittent line). See how those circles fit better inside the airfoil compared to the first picture.
In the picture below the 2nd iteration of the camber line is shown, along with the mean line from the first picture as to illustrate the difference between the two. Those circles are fitting even better now inside (except that first one which flew out, but don't mind him).
From what I can gather from your diagram, the camber line is defined by it being the line whose tangent bisects the angle between the two tangents of the upper and lower edges.
In other words, your camber line is always the mean point between the two edges, but along a line of shortest distance between the top and bottom edges.
So, given the y-coordinates y=top(x) and y=bot(x), why don't you:
<pseudocode>
for each x:
find x2 where top(x)-bot(x2) is minimized
camber( mean(x,x2) ) = mean( top(x),bot(x2) )
</pseudocode>
and then interpolate etc.?
edit
Sorry! On second thought I think that should be
find x2 where ( (top(x)-bot(x2))^2 + (x-x2)^2 ) is minimised
obviously you should be minimising the length of that perpendicular line.
Is that right?
I'm new to stack overflow but this is a problem I have worked on quite a bit and thought I would post an alternate approach to the problem.
This approach uses the concept of a Voronoi diagram:
http://en.wikipedia.org/wiki/Voronoi_diagram
Essentially, a map is created which divides the space into regions containing one of the input points (x,y of your airfoil). The important part here is that any point within the region is closest to the input point in that region. The nodes created by this space division are equidistant to at least three of the input points.
Here is the interesting part: three equidistant points from a center point can be used to create a circle. As you mentioned, inscribed circle center points are used to draw the mean camber line because the inscribed circle measures the thickness.
We are close now. The nature of the voronoi diagram in this application means that any voronoi node inside of our airfoil region is the center point of one of these "thickness circles." (This runs into some issue very close to the LE and TE depending on your data. I usually apply some filtering here).
Basic Structure:
Create Voronoi Diagram
Extract Voronoi Nodes
Determine Nodes Which Lie Within Airfoil
Construct Mean Camber Line From Interior Nodes
Most of my work is in Matlab which has built in voronoi and inpolygon functions. As such, I'm not a huge help in developing those functions but they should be well documented elsewhere.
Trailing Edge/Leading Edge Issues
As I am sure you have experienced or know, it is difficult to measure thickness well when close to the LE/TE. This approach will contruct a fork in the nodes when the thickness circle is less than the edge radius. A check of the data for this fork will find the points which are false for the camber line. To construct the camber line all the way to the edge of the foil you could extrapolate your camber line (2nd or 3rd order should be fine) and find the intersection.
I think the best way for drawing the camber line of an airofoil is to load the profile in CATIA. After that in CATIA we can draw circles that are tangent to the both side of profile (suction side and pressure side. Then we can connect center of these circles and consequently we find the camber line accurately.
Is the mean camber line the set of points equidistant from the upper line and the lower line? If that's the definition, it's different from Sanjay's, or at least not obviously-to-me the same.
The most direct way to compute that: cast many rays perpendicular to the upper line, and many rays perpendicular to the lower line, and see where the rays from above intersect the rays from below. The intersections with the nearest-to-equal distances approximate the mean camber line (as defined here); interpolate them, with the differences in distance affecting the weights.
But I'll bet the iterative method you pasted from comments is easier to code, and I guess would converge to the same curve.

Resources