How to represent a polygon with hole(s)? - matlab

It's usually popular to work with polygons with their vertices sorted CW or CCW in vectors(2*1 or 1*2 matrices). However, how to state polygons with holes in vectors?
I'm going to apply various process on these polygons, so I want a way of representing with which I could work easily or efficiently.(i.e how to state that kind of polygons in my program in order to ease my algorithms?)
polygons are 2D and I'm programming in MATLAB.
EDIT 1 : I'm going to calculate visibility graph of these polygons(with or without holes).

As others have mentioned, a polygon with holes can be represented as an exterior boundary, plus zero or more interior boundaries, all of which are mutually nonoverlapping*. If you use nonzero winding number to determine inside/outside, be sure to specify your interior boundaries in the opposite direction as the exterior boundaries (counterclockwise for exterior and clockwise for interior, or vice-versa) so that the contour integrals are zero inside the holes.
FYI, tis kind of definition/representation has been formalized in the OpenGIS Simple Features Specification (PDF).
As far as representation:
I'd probably have a cell array of K Nx2 matrices, where the first element in the cell array is the exterior boundary, and the remaining elements (if any) in the cell array are the interior boundaries. I would use a cell array because there may not be the same number of points on each boundary.
*nonoverlapping = except at individual points, e.g. a diamond inside a square:

You can break a polygon with a hole in it into two shapes without a hole. When you're doing contour integration in a complex plane, you can create a "cut" from one edge of the polygon that brings you to the edge of the hole; integrate around one side of the hole and back; then traverse around the other side for the second polygon. You end up with two path integrals along each cut that cancel each other out.
"visibility graph" - is this for a radiation view factor calculation with shading? Or a ray-tracing graphics algorithm?

A polygon, plus a list of polygonal holes. Just be sure the various polygons don't intersect.
What do you plan to do with this thing?

It sounds like each hole is just a polygon inside the polygon itself. Perhaps you could store a vector like you describe for the outer polygon, then a vector of more polygon vectors for the holes.

Presumably you'll want to have a tree structure if you want this to be as generic as possible (i.e. polygons with polygonal holes that have polygons inside them with holes inside that, ...). Matlab isn't really great at representing tree structures efficiently, but here's one idea...
Have a struct-array of polygons.
Each polygon is a struct with two fields, 'corners', and 'children'.
The 'corners' field contains a matrix of (x,y) coordinates of the corners, accessed as "data{polyIdx}.corners(:,cornerIdx)".
The 'children' field is a struct-array of polygons.
Here's an example of some code to make a triangle with bogus children that are holes (they aren't really valid though because they will likely overlap:
polygon = struct;
npoints = 3;
polygon.corners = rand(2,npoints);
polygon.children = struct;
nchildren = 5;
for c=1:nchildren
polygon.children(c).corners = rand(2,npoints);
polygon.children(c).children = struct;
end
You could continue to recursively define children that alternate between creating holes and filling them.

What exactly do you mean under "a visibility graph" ?
Two "full" poligons, two states possible, either +1 or -1.
If you're representing a hole, you've got one with state +1 and one with state -1, which represents a hole, resulting in state 0.
If you've got overlapping polygons, you'll end up with resultant state >1. Then you can calculate the borders of a new polygon.
If you've got two polygons with holes that intersect, then first calculate the state of a new polygon which consists of outer borders of the two old ones, then deal with holes.
Anyways, ... I think you get the general principle.
Have no idea how to do it in matlab, I used it only marginally so far, and even that for very simple things.

Related

Is there a concave-hull algorithm where points to be excluded can be specifed?

So I have a list of points (2d) that should be inside a polygon, and a second list of points that should be outside the polygon. I want to find the polygon that encloses the "inside" points while excluding the "outside" points.
The resulting polygon will almost certainly be concave. I would like to minimise the number of edges it has, but any other sensible criteria would probably do. It seems likely that some approach that started with the convex hull, and then took chunks out of it would work.
I am wondering if this could be achieved using alpha shapes, while varying alpha. There is already a nice python implementation for that; https://pypi.org/project/alphashape/
but I haven't worked out exactly how I'd need to vary alpha.

Intersection over union for rectangles with different orientation

I need to implement an algorithm in swift to find the intersection over union (IoU) between two rectangles with different orientations in 2-dimensional space. I could not find any tutorials or sample codes to teach how to implement such an algorithm.
Could someone provide relevant resources?
You can use O'Rourke algorithm for calculation of intersection of two convex polygons.
C and Java code is availaible on the page for book "Computational Geometry in C"
Algorithm traverses edges of polygons until it finds intersection (using
orientation test). After intersection it chooses "the most inner" edge from two possible next ones to build intersection core polygon (always convex).
When you have ordered list of vertices, you can calculate polygon area with shoelace formula.
To get area of union, we can calculate (thanks to Yves Daoust for hint)
Area(Union) = Area(P) + Area(Q) - Area(Intersection)
Alternatively to the very good solution of MBo/O'Rourke, you can use a sweep line approach.
For convenience, assume that one of the polygons is axis aligned. Then there are two "events" when the line hits the top and bottom sides of the aligned rectangle and four events when the line hits the vertices of the other (depending on the orientation, there are 8 possible permutations of the vertices).
The intersection of the rectangles occurs inside the vertical ranges defined by these events (you perform a merge of the two event sets) and there are up two six intersections to be computed between the oblique sides and the horizontals. For every event line, it is an easy matter to determine the X intervals spanned by both rectangles, and find their intersection or union. And the areas between two event lines are trapezoids.
To cope with rectangles in general position, you can
rotate both polygons to align one of them,
work with a counter-rotated coordinate system,
perform the sweep with an horizontal line anyway without moving the polygons; but then there are 8 events instead of 6 and up to 8 intersection computations.

Extract contour from obj 3d object in Matlab

I have an .obj file representing a 3D object.
I need to extract from this 3D object the contour that is obtained by intersection with a plane. So for example, I have an object representing a cylinder oriented with vertical axis, then I want to extract a circle contour when the intersecting plane is horizontal or a rectangular contour when the intersection plane is vertical. Any suggestion about how to do it?
Since I didn't know how to visualise this obj file, I have converted to a patch with the following code (some function taken from loadawobj from Matlab file exchange).
modelname='file.obj';
S=loadawobj(modelname);
mtl=loadawmtl(['obj/' S.mtllib]);
p3=patch('Vertices',S.v','Faces',S.f3');
for ii=1:length(S.umat3)
mtlnum=S.umat3(ii);
fvcd3(ii,:)=mtl(1).Kd';
end
p3.FaceVertexCData=fvcd3;
p3.FaceColor='flat';
But I don't necessarily need to extract the contour from the resulting patch if this is too complex to accomplish. If there is an easier procedure starting from the obj file, it's also fine and acceptable. Thank you!
That's the way I solved the problem, after collecting information all around the web. I couldn't find anything ready on line so I had to implement an algorithm on my own. The basic idea is very simple but there are many steps required. I start from two info: one array containing the coordinates of the cloud point and another array containing a bunch of tuples about how the 3 vertex are connected to form a triangle.
First of all you need to find a representation of the plane you want to use for your cutting. That means you just use one point and the normal to the plane to represent it. That plane is required in order to identify the cutting point on the structure.
Second step is to identify the triangles on the plane. In few words you just need to scroll over all the triangles of the structure and find those having one corner above the cutting plane and another corner below the cutting plane. Also don't forget to account for the condition where one corner is on the plane or two are on the plane. All the other triangles are not needed, since they are totally above or below the cutting plane.
Now you have a subset of all your triangles. You need to extract points of the contour. So for each triangle you have 3 vertex: in general case you can imagine that one vertex is above the plane and the other two are below. Then you have two lines cutting the plane. You can extract two point by simply intersecting these lines with the cutting plane.
By repeating this operation you get a series of points on 2D space. But they have no order and if you plot them as a continuous plot, you get lines jumping up and down since the points you have extracted are randomly located in the array. So, it's required to order them in a proper way. The method I used is the very simple: start from one point and connect to the closest one. There are some bad situations where that doesn't work but you can probably avoid it by adding some more rules on the algorithm.

Subtract delaunay surfaces from each other

I have a surface by the code below and another surface which is created by the exact same code. I want to see the height differences in another figure. How am I able to do that? Already operated with the Minus-operator but this won't work.
Furthermore the matrices have NOT the same size!
Appreciate your help!
x1 = Cx1;
y1 = Cy1;
z1 = Cz1;
tri1 = delaunay(x1,y1);
fig1 = figure%('units','normalized','outerposition',[0 0 1 1]);
trisurf(tri1,x2,y2,z2)
xlabel('x [mm] ','FontSize',30)
ylabel('y [mm] ','FontSize',30)
zlabel('z [mm] ','FontSize',30)
The simplest way to solve this problem is to interpolate from one mesh onto the other one. Such an approach works well when one is more highly resolved than the other, or when you're not as concerned with results at individual nodes, but rather the overall pattern across elements. If that's not the case, then you have a very complicated problem because you need to create a polygonal surface that fully captures all nodes and edges of both triangulations. Consider the following pair of triangular patterns:
A surface that captured all the variations would need to have all the vertices and edges that make up both of them, which is not a purely triangular surface. So, let us instead assume the easier case. To map results from one triangulation to the other, you simply need to formulate functions that define how the values vary along the triangles, which are more broadly called basis functions. It is often assumed that values betweeen the nodes (i.e. vertices) of the triangles vary linearly along the surfaces of the triangles. You can do it differently if you want, it just requires defining new basis functions. If we go for linear functions, then the equations in 2D are pretty simple. Let's say you make an array trimap that has which triangle each of the vertices of the other triangulation is inside of. This can be accomplished using the info here. Then, we set the coordinates of the vertices of the current triangle to (x1,y1), (x2,y2), and (x3,y3), and then do the math:
for cnt1=1,npoints
x1=x(tri1(trimap(cnt1),1));
x2=x(tri1(trimap(cnt1),2));
x3=x(tri1(trimap(cnt1),3));
y1=y(tri1(trimap(cnt1),1));
y2=y(tri1(trimap(cnt1),2));
y3=y(tri1(trimap(cnt1),3));
delta=x2*y3+x1*y2+x3*y1-x2*y1-x1*y3-x3*y2;
delta1=(x2*y3-x3*y2+xstat(cnt1)*(y2-y3)+ystat(cnt1)*(x3-x2));
delta2=(x3*y1-x1*y3+xstat(cnt1)*(y3-y1)+ystat(cnt1)*(x1-x3));
delta3=(x1*y2-x2*y1+xstat(cnt1)*(y1-y2)+ystat(cnt1)*(x2-x1));
weights(cnt1,1)=delta1/delta;
weights(cnt1,2)=delta2/delta;
weights(cnt1,3)=delta3/delta;
z1=z(tri1(trimap(cnt1),1));
z2=z(tri1(trimap(cnt1),2));
z3=z(tri1(trimap(cnt1),3));
valinterp(cnt1)=sum(weights(cnt1,:).*[z1,z2,z3]);
end
valinterp is the interpolated value for each point. Here and here are some nice slides explaining the mathematics behind all this. Note that I've not tested any of this code. Note also that you will need to do something to assign to values outside of the triangulation. Perhaps a null value, or an inverse-distance weighted value.

How to find closest points between two convex hull in MATLAB?

In part of an Artificial Neural Network matlab code, I want to find nearest points of two convex polygons.
I saw
dsearchn(X,T,XI)
command's description here, but that finds closest points between two sets of points, and polygons (like convexs) have infinites points.
So can you suggest any way/idea?
Notice: I'm using MATLAB 2014a. I have the coordinate of each convex's vertex point.
If you are not happy with what is provided by dsearchn, then, If I were you, I would do one of two following:
Find Nearest Neighbours on the vertices (for example which vertex of
polygon A is the NN of a given vertex of polygon B).
Pick a random point inside polygon A (you may want to compute the
convex hull of A, but you may skip that and take into account only
the vertices you know already). That random point is the query. Find
an NN of that point from the vertices of polygon B.
You may want to ask in Software recommendations for more.
Edit:
Another approach is this:
Create a representative dataset of polygon A. Set the size of the dataset yourself and fill it with samples of points that lie inside the polygon. Choose them uniformly randomly inside the polygon.
Then take a point of polygon B (either a vertex or a random point inside polygon B) and that's the query point, for which you will seek Nearest Neighbour(s) inside the representative dataset of polygon A.
Of course that's just an approximation, but I can't think of something else now.
Notice that you can of course do the same for polygon B.
With This File in File Exchange, I've find the solution.
With a little code modification, I have drawn a perpendicular bisector which I wanted. Of course, this way is time consuming.