Let's say I have a polygon, and I want to mesh it. In order to further put constraints on the mesh I get, I will supply a list of fix points ( which must lie inside the polygon) so that they must be connected by the triangle elements generated.
What is the matlab command to do it? I tried delaunay command, but it can't work on concave polygon because the delaunay command will always return me a list of elements that encompass a convex area.
The function you want to use is DelaunayTri, and you would follow these steps to do it:
Create a list of the edge points in your polygon.
Take all of the vertex points of your polygon and combine them with the additional fixed points you want to include inside the polygon.
Create a constrained triangulation (as I've illustrated in other answers here and here).
As you noted, this will create a triangulation of the convex hull (even if you have a concave polygon), so you would have to remove triangles outside of the constrained edges using the method inOutStatus (also illustrated in the answers linked above).
Here's some sample code:
polygonVertices = [0 0;... %# Concave polygon vertices
0 1;...
1 1;...
0.5 0.5;...
1 0];
polygonEdges = [1 2;... %# Polygon edges (indices of connected vertices)
2 3;...
3 4;...
4 5;...
5 1];
otherVertices = [0.5.*rand(5,1) rand(5,1)]; %# Additional vertices to be added
%# inside the polygon
vertices = [polygonVertices; otherVertices]; %# Collect all the vertices
dt = DelaunayTri(vertices,polygonEdges); %# Create a constrained triangulation
isInside = inOutStatus(dt); %# Find the indices of inside triangles
faces = dt(isInside,:); %# Get the face indices of the inside triangles
And now the variables faces and vertices can be used to plot the meshed polygon.
Working with older versions of MATLAB...
Looking through the archived version documentation (note: a MathWorks account is required to do so), one can see that DelaunayTri first appeared in version 7.8.0 (2009a). Prior to that, the only built-in functionality available for performing 2-D Delaunay triangulation was delaunay, which was based on Qhull and was thus unable to support constrained triangulations or triangulations of non-convex surfaces.
The newer DelaunayTri uses CGAL. As such, one option for users of versions older than 7.8.0 is to create MEX-files to interface CGAL routines in MATLAB. For example, if you're faced with triangulating a concave polygon, you can create a MEX-file to interface one of the convex partitioning routines in CGAL in order to break the concave polygon into a set of convex polygons. Then delaunay could be used to triangulate each convex polygon, and the final set of triangulations grouped into one larger triangulation of the concave polygon.
Related
Shown Figure (1) is a typical Delaunay triangulation (blue) and it has a boundary line (black rectangle).
Each vertex in the Delaunay triangulation has a height value. So I can calculate the height inside convex hull. I am figuring out a method to calculate the height up to the boundary line (some sort of extrapolation).
There are two things associated with this task
Triangulate up to the boundary point
Figuring out the height at newly created triangle vertices
Anybody come across this issue?
Figure 1:
I'd project the convex hull points of the triangulation to the visible box segments and then insert the 4 box corners and the projected points into the triangulation.
There is no unique correct way to assign heights to the new points. One easy and stable method would be to assign to each new point the height of the closest visible convex hull vertex. Be careful with extrapolation: Triangles of the convex hull tend to have unstable slopes, see the large triangles in front of the below terrain image. Their projection to the xy plane has almost 0 area but due to the height difference they are large and almost 90 degrees to the xy plane.
I've had some luck with the following approach:
Find the segment on the convex hull that is closet to the extrapolation point
If I can drop a perpendicular onto the segment, interpolate between the two vertices of the segment.
If I can not construct the perpendicular, just use the closest vertex
This approach results in a continuous surface, but does not provide 1st derivative continuity.
You can find some code that might be helpful at TriangularFacetInterpolator.java. Look for the interpolateWithExteriorSupport method.
I'm trying to get the Trajectory from Voronoi Diagram using the library voronoi from Matlab. I'm using this code:
vo = (all the obstacles from a binary picture, plotted in a figure), where:
vo(1,:) : x-axis points
vo(2,:) : y-axis points
Code:
figure; hold on;
plot(vo(1,:),vo(2,:),'sr');
[vx,vy] = voronoi(vo(1,:),vo(2,:));
plot(vx,vy,'-b');
Obtaining:
In other words, how can I separate all the useless lines from the real trajectory?
The distinguishing property of the useless lines in this case is that they contain at least one vertex inside the polygonal obstacles.
There are many ways you might choose to decide if a vertex satisfies this condition but given that the coordinates come from a binary image, one of the most straightforward might be to check if the vertex comes within a pixel's distance of any point in vo:
[~,D] = knnsearch(vo,[vx(:),vy(:)]);
inObstacle = any(reshape(D,size(vx)) < 1);
plot(vx(:,~inObstacle),vy(:,~inObstacle),'-b');
If you cannot rely on the obstacles being filled with pixels (e.g. they may be hollow) then you probably need to determine which pixels belong to the same obstacle (perhaps using kmeans or bwconncomp) and then eliminate Voronoi edges that intrude into each object's convex hull. For a given obstacle made up of the pixels in vo listed by the linear indices idx:
K = convhull(vo(idx,1),vo(idx,2));
inObstacle = inpolygon(vx,vy,vo(idx(K),1),vo(idx(K),2));
I created 3D convex hull plot in Matlab. It seems in this function, some of laser points were used for facets of convex hull, but some other points are situated inside convex hull . My question is that how can I identify these points in Matlab separately. Which way is applicable for calculating the perpendicular distance of these points situated inside of convex hull to the nearest convex hull facet (distance from each point to the closest facet of the convex hull)?
I would be very grateful if you could introduce me some references about convex hull function.
On the Matlab file exchange, there is a great function called inhull, which will test whether your points are inside the hull or not. I'm not sure that it provides the distance from the points to the nearest facet, but perhaps the methods used in the code would be simple to change to provide this output.
Check out the function, tsearchn.
The following code creates a sphere in 3D and computes the delaunay triangularization. We then set-up testpoints variable with points to test if they are inside the sphere or not. t returns indices back into TRI for tetrahedra facet that are closest to the point or NaN if the point is outside the sphere.
[X,Y,Z] = sphere(N);
TRI = delaunay(X(:),Y(:),Z(:));
testpoints = [0 0 0; 0 .5 0; 1 2 0]
t = tsearchn([X(:) Y(:) Z(:)],TRI,testpoints)
figure;
trisurf(TRI,X(:),Y(:),Z(:));
Output is,
t =
8182
7779
NaN
I want to generate a binary mask that has ones for all voxels inside and zeros for all voxels outside a volume. The volume is defined by the convex hull around a set of 3D coordinates (<100; some of the coordinates are inside the volume).
I can get the convex hull using CONVHULLN, but how do I convert that into a binary mask?
In case there is no good way to go via the convex hull, do you have any other idea how I could create the binary mask?
You can solve this problem using the DelaunayTri class and the pointLocation method. Here's an example:
pointMatrix = rand(20,3); %# A set of 20 random 3-D points
dt = DelaunayTri(pointMatrix); %# Create a Delaunay triangulation
[X,Y,Z] = meshgrid(0:0.01:1); %# Create a mesh of coordinates for your volume
simplexIndex = pointLocation(dt,X(:),Y(:),Z(:)); %# Find index of simplex that
%# each point is inside
mask = ~isnan(simplexIndex); %# Points outside the convex hull have a
%# simplex index of NaN
mask = reshape(mask,size(X)); %# Reshape the mask to 101-by-101-by-101
The above example creates a logical mask for a 101-by-101-by-101 mesh spanning the unit volume (0 to 1 in each dimension), with a 1 (true) for the mesh points inside the convex hull of the 3-D point set.
It's late here, so only a very sketchy suggestion:
With the points from your convex hull construct a Delaunay tessellation.
Using the pointLocation method of the DelaunayTri class test every point in your array of pixels.
I expect that this will be very slow, and that there are better solutions, if one comes in my dreams I'll post again tomorrow.
This is a scan conversion problem. Check out section 8 of 3D Scan-Conversion Algorithms for Voxel-Based Graphics.
The algorithm you want is the solid one, and is slightly simpler since you are voxelizing a convex polyhedron whose faces are triangles - each "voxel" run is bounded by two triangles.
I have a polyhedron, with a list of vertices (v) and surfaces (s). How do I break this polyhedron into a series of tetrahedra?
I would particularly like to know if there are any built-in MATLAB commands for this.
For the convex case (no dents in the surface which cause surfaces to cover each other) and a triangle mesh, the simple solution is to calculate the center of the polyhedron and then connect the three corners of every face with the new center.
If you don't have a triangle mesh, then you must triangulate, first. Delaunay triangulation might help.
If there are holes or caves, this can be come arbitrarily complex.
I'm not sure the OP wanted a 'mesh' (Steiner points added) or a tetrahedralization (partition into tetrahedra, no Steiner points added). for a convex polyhedron, the addition of Steiner points (e.g. the 'center' point) is not necessary.
Stack overflow will not allow me to comment on gnovice's post (WTF, SO?), but the proof of the statement "the surfaces of a convex polyhedron are constraints in a Delaunay Tesselation" is rather simple: by definition, a simplex or subsimplex is a member in the Delaunay Tesselation if and only if there is a n-sphere circumscribing the simplex that strictly contains no point in the point set. for a surface triangle, construct the smallest circumscribing sphere, and 'puff' it outwards, away from the polyhedron, towards 'infinity'; eventually it will contain no other point. (in fact, the limit of the circumscribing sphere is a half-space; thus the convex hull is always a subset of the Delaunay Tesselation.)
for more on DT, see Okabe, et. al, 'Spatial Tesselations', or any of the papers by Shewchuk
(my thesis was on this stuff, but I remember less of it than I should...)
I would suggest trying the built-in function DELAUNAY3. The example given in the documentation link resembles Aaron's answer in that it uses the vertices plus the center point of the polyhedron to create a 3-D Delaunay tessellation, but shabbychef points out that you can still create a tessellation without including the extra point. You can then use TETRAMESH to visualize the resulting tetrahedral elements.
Your code might look something like this (assuming v is an N-by-3 matrix of vertex coordinate values):
v = [v; mean(v)]; %# Add an additional center point, if desired (this code
%# adds the mean of the vertices)
Tes = delaunay3(v(:,1),v(:,2),v(:,3)); %# Create the triangulation
tetramesh(Tes,v); %# Plot the tetrahedrons
Since you said in a comment that your polyhedron is convex, you shouldn't have to worry about specifying the surfaces as constraints in order to do the triangulation (shabbychef appears to give a more rigorous and terse proof of this than my comments below do).
NOTE: According to the documentation, DELAUNAY3 will be removed in a future release and DelaunayTri will effectively take its place (although currently it appears that defining constrained edges is still limited to only 2-D triangulations). For the sake of completeness, here is how you would use DelaunayTri and visualize the convex hull (i.e. polyhedral surface) as well:
DT = DelaunayTri(v); %# Using the same variable v as above
tetramesh(DT); %# Plot the tetrahedrons
figure; %# Make new figure window
ch = convexHull(DT); %# Get the convex hull
trisurf(ch,v(:,1),v(:,2),v(:,3),'FaceColor','cyan'); %# Plot the convex hull