Is there an optimal algorithm which can be compute a L_inf Delaunay triangulation directly? - triangulation

I want to write a C++ program which draws a Delaunay triangulation of a point set in the plane using L_inf metric.
I wonder if a Divide & Conquer algorithm (from Guibas and Stolfi) and an incremental algorithm (from Bowyer-Watson) can be applied to L_inf metric.
There have been a lot of works which prove that L_p Delaunay triangulation can be done in O(nlogn), but many of them proved it indirectly by computing Voronoi diagram. I want to implement a program computing Delaunay triangulation directly, not from a Voronoi diagram.

I'm much of a C++ guy but in Python this would probably be my approach:
def delaunay(points):
# Sort the points lexicographically (tuples are compared lexicographically).
points = sorted(points)
# Initialize the list of supertriangle(s).
supertriangle = [[-2, -1, -2], [-1, -2, -2], [-2, -2, -2]]
# Initialize the list of triangles.
triangles = []
# Initialize the list of edges.
edges = []
# For each point:
for p in points:
# Insert a point into the edge list.
edges.append([p, p])
# Create the supertriangle
triangle = [[0, 1, 2], supertriangle]
triangles.append(triangle)
while True:
# This is the end of the algorithm if no more edges are intersecting.
if len(edges) == 0:
break
# Find the point of intersection of the smallest edge.
edge = sorted(edges)[0]
# Remove the edge from the edge list.
edges.remove(edge)
# Find the triangle containing the edge.
triangle = None
for t in triangles:
if edge[0] in t[0] and edge[1] in t[0]:
triangle = t
break
# Remove the triangle from the triangle list.
triangles.remove(triangle)
# Find the indices of the edge endpoints.
index1 = triangle[0].index(edge[0])
index2 = triangle[0].index(edge[1])
# Form a new triangle for each endpoint.
triangle1 = [
[triangle[0][(index1 + 1) % 3], triangle[0][(index1 + 2) % 3], edge[1]],
triangle[1],
]
triangle2 = [
[triangle[0][(index2 + 1) % 3], triangle[0][(index2 + 2) % 3], edge[0]],
triangle[1],
]
# Add the new
triangles.append(triangle1)
triangles.append(triangle2)
# Form the new edges
edges.append([triangle1[0][0], triangle2[0][0]])
edges.append([triangle1[0][0], triangle1[0][1]])
edges.append([triangle1[0][1], triangle2[0][0]])
edges.append([triangle2[0][1], triangle2[0][0]])
# Remove triangles that have a supertriangle vertex.
triangles = [t for t in triangles if -1 not in t[0]]
# Remove duplicate triangles.
triangles = [dict(t) for t in set(tuple(t) for t in triangles)]
# Return the list of triangles.
return triangles

Jonathan Shewchuk's Triangle is a well regarded implementation in C and there is also the CGAL 2D Triangulation which is C++. My own Tinfour implementation is in Java, so it's not quite what you're looking for, but the project does have a set example applications and some implementation notes that may be of use at Tinfour Algorithms

Related

Can there be overlap in k-means clusters?

I am unclear about why k-means clustering can have overlap in clusters. From Chen (2018) I saw the following definition:
"..let the observations be a sample set to be partitioned into K disjoint clusters"
However I see an overlap in my plots, and am not sure why this is the case.
For reference, I am trying to cluster a multi-dimensional dataset with three variables (Recency, Frequency, Revenue). To visualize clustering, I can project 3D data into 2D using PCA and run k-means on that. Below is the code and plot I get:
df1=tx_user[["Recency","Frequency","Revenue"]]
#standardize
names = df1.columns
# Create the Scaler object
scaler = preprocessing.StandardScaler()
# Fit your data on the scaler object
scaled_df1 = scaler.fit_transform(df1)
df1 = pd.DataFrame(scaled_df1, columns=names)
df1.head()
del scaled_df1
sklearn_pca = PCA(n_components = 2)
X1 = sklearn_pca.fit_transform(df1)
X1 = X1[:, ::-1] # flip axes for better plotting
kmeans = KMeans(3, random_state=0)
labels = kmeans.fit(X1).predict(X1)
plt.scatter(X1[:, 0], X1[:, 1], c=labels, s=40, cmap='viridis');
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
def plot_kmeans(kmeans, X, n_clusters=4, rseed=0, ax=None):
labels = kmeans.fit_predict(X)
# plot the input data
ax = ax or plt.gca()
ax.axis('equal')
#ax.set_ylim(-5000,7000)
ax.scatter(X[:, 0], X[:, 1], c=labels, s=40, cmap='viridis', zorder=2)
# plot the representation of the KMeans model
centers = kmeans.cluster_centers_
radii = [cdist(X[labels == i], [center]).max()
for i, center in enumerate(centers)]
for c, r in zip(centers, radii):
ax.add_patch(plt.Circle(c, r, fc='#CCCCCC', lw=3, alpha=0.5, zorder=1))
kmeans = KMeans(n_clusters=4, random_state=0)
plot_kmeans(kmeans, X1)
My question is:
1. Why is there an overlap? Is my clustering wrong if there is?
2. How does k-means decide cluster assignment incase there is an overlap?
Thank you
Reference:
Chen, L., Xu, Z., Wang, H., & Liu, S. (2018). An ordered clustering algorithm based on K-means and the PROMETHEE method. International Journal of Machine Learning and Cybernetics, 9(6), 917-926.
K-means computes k clusters by average approximation. Each cluster is defined by their computed center and thus is unique by definition.
Sample assignment is made to cluster with closest distance from cluster center, also unique by definition. Thus in this sense there is NO OVERLAP.
However for given distance d>0 a sample may be within d-distance to more than one cluster center (it is possible). This is what you see when you say overlap. However still the sample is assigned to closest cluster not to all of them. So no overlap.
NOTE: In the case where a sample has exactly same closest distance to more than one cluster center any random assignment can be made between the closest clusters and this changes nothing important in the algorithm or results since clusters are re-computed after assignment.
Kmeans algorithm is an iterative algorithm that tries to partition the dataset into K-pre-defined distinct non-overlapping subgroups (clusters) where each data point belongs to only one group. It tries to make the inter-cluster data points as similar as possible while also keeping the clusters as different (far) as possible. It assigns data points to a cluster such that the sum of the squared distance between the data points and the cluster’s centroid (arithmetic mean of all the data points that belong to that cluster) is at the minimum. The less variation we have within clusters, the more homogeneous (similar) the data points are within the same cluster.
Perhaps you did something wrong... I don't have your data, so I can't test it. You can add boundaries, and check those. See the sample code below.
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi
def voronoi_finite_polygons_2d(vor, radius=None):
"""
Reconstruct infinite voronoi regions in a 2D diagram to finite
regions.
Parameters
----------
vor : Voronoi
Input diagram
radius : float, optional
Distance to 'points at infinity'.
Returns
-------
regions : list of tuples
Indices of vertices in each revised Voronoi regions.
vertices : list of tuples
Coordinates for revised Voronoi vertices. Same as coordinates
of input vertices, with 'points at infinity' appended to the
end.
"""
if vor.points.shape[1] != 2:
raise ValueError("Requires 2D input")
new_regions = []
new_vertices = vor.vertices.tolist()
center = vor.points.mean(axis=0)
if radius is None:
radius = vor.points.ptp().max()*2
# Construct a map containing all ridges for a given point
all_ridges = {}
for (p1, p2), (v1, v2) in zip(vor.ridge_points, vor.ridge_vertices):
all_ridges.setdefault(p1, []).append((p2, v1, v2))
all_ridges.setdefault(p2, []).append((p1, v1, v2))
# Reconstruct infinite regions
for p1, region in enumerate(vor.point_region):
vertices = vor.regions[region]
if all([v >= 0 for v in vertices]):
# finite region
new_regions.append(vertices)
continue
# reconstruct a non-finite region
ridges = all_ridges[p1]
new_region = [v for v in vertices if v >= 0]
for p2, v1, v2 in ridges:
if v2 < 0:
v1, v2 = v2, v1
if v1 >= 0:
# finite ridge: already in the region
continue
# Compute the missing endpoint of an infinite ridge
t = vor.points[p2] - vor.points[p1] # tangent
t /= np.linalg.norm(t)
n = np.array([-t[1], t[0]]) # normal
midpoint = vor.points[[p1, p2]].mean(axis=0)
direction = np.sign(np.dot(midpoint - center, n)) * n
far_point = vor.vertices[v2] + direction * radius
new_region.append(len(new_vertices))
new_vertices.append(far_point.tolist())
# sort region counterclockwise
vs = np.asarray([new_vertices[v] for v in new_region])
c = vs.mean(axis=0)
angles = np.arctan2(vs[:,1] - c[1], vs[:,0] - c[0])
new_region = np.array(new_region)[np.argsort(angles)]
# finish
new_regions.append(new_region.tolist())
return new_regions, np.asarray(new_vertices)
# make up data points
np.random.seed(1234)
points = np.random.rand(15, 2)
# compute Voronoi tesselation
vor = Voronoi(points)
# plot
regions, vertices = voronoi_finite_polygons_2d(vor)
print("--")
print(regions)
print("--")
print(vertices)
# colorize
for region in regions:
polygon = vertices[region]
plt.fill(*zip(*polygon), alpha=0.4)
plt.plot(points[:,0], points[:,1], 'ko')
plt.axis('equal')
plt.xlim(vor.min_bound[0] - 0.1, vor.max_bound[0] + 0.1)
plt.ylim(vor.min_bound[1] - 0.1, vor.max_bound[1] + 0.1)
Great resource here.
https://scikit-learn.org/stable/auto_examples/cluster/plot_kmeans_digits.html

How to identify multiple intersecting polygons in MATLAB?

I'm trying to identify overlapping/intersecting polygons. The techniques I have found only compare two polygons at a time. I have tens-of-thousands of cells in a dataset, and in each one there are 2-20 polygons, each described by x-y coordinates. I want to find the overlapping polygons in each cell. Looping between every pair to check for an intersection is very slow, so I want to ask...
Is there a way to compare all polygons at the same time and extract the IDs of those that are overlapping?
Here is a simple example of a single entry from the dataset:
shapes = cell(4,2);
shapes{1,1} = 'poly1';
shapes{2,1} = 'poly2';
shapes{3,1} = 'poly3';
shapes{4,1} = 'poly4';
shapes{1,2} = [1, 3, 3; 1, 1, 3]';
shapes{2,2} = [2, 4, 2; 2, 2, 5]';
shapes{3,2} = [4, 5, 5, 4; 3, 3, 5, 5]';
shapes{4,2} = [1, 3, 3, 1; 4, 4, 6, 6]';
This example contains these 4 polygons:
This plot was made with separate 'polyshape' objects, but that doesn't mean I need to use this kind of object in the solution.
The output I would like is a record of each overlapping pair:
result =
2×2 cell array
{'poly1'} {'poly2'}
{'poly2'} {'poly4'}
P.S. My current method is to loop through each pair and use the poly2mask function on each polygon of the pair. Then use the & operator to add the binary masks together. This produces a logical array of 1's where there is any overlap.
P.P.S. The actual polygons I am looking at are all annular sectors, therefore they are not all convex
Here is a solution that makes use of 'polyshape' vectors and avoids making all those pairwise comparisons in extra loops (although I don't know how the 'overlap' function works).
% Set up empty vector to hold the different shapes
polyvec = [];
% Loop all shapes and combine into polyshape vector
for ii = 1 : size(shapes, 1)
poly = polyshape(shapes{ii,2}(:,1), shapes{ii,2}(:,2));
% When you combine polyshape objects together the you get
% a vector that is of the polyshape object type
polyvec = [polyvec, poly];
end
% Use the overlap function to compute a symmetric binary matrix
% of which polygons in the polygon vector overlap.
interMatSym = overlaps(polyvec);
% I only need the upper triangle of the symmetric interaction
% matrix and all polygons overlap with themselves so use 'triu'
interMat = triu(overlaps(polyvec), 1);
% Find the coordinates of the overlap in the interaction matrix
[x, y] = find(interMat);
% Save the result
result = [shapes(x,1), shapes(y,1)];
result =
2×2 cell array
{'poly1'} {'poly2'}
{'poly2'} {'poly4'}
If there is a way to create a polyshpae vector any more efficiently then I'd love to know!

Fitting largest circle in free area in image with distributed particle

I am working on images to detect and fit the largest possible circle in any of the free areas of an image containing distributed particles:
(able to detect the location of particle).
One direction is to define a circle touching any 3-point combination, checking if the circle is empty, then finding the largest circle among all empty circles. However, it leads to a huge number of combination i.e. C(n,3), where n is the total number of particles in the image.
I would appreciate if anyone can provide me any hint or alternate method that I can explore.
Lets do some maths my friend, as maths will always get to the end!
Wikipedia:
In mathematics, a Voronoi diagram is a partitioning of a plane into
regions based on distance to points in a specific subset of the plane.
For example:
rng(1)
x=rand(1,100)*5;
y=rand(1,100)*5;
voronoi(x,y);
The nice thing about this diagram is that if you notice, all the edges/vertices of those blue areas are all to equal distance to the points around them. Thus, if we know the location of the vertices, and compute the distances to the closest points, then we can choose the vertex with highest distance as our center of the circle.
Interestingly, the edges of a Voronoi regions are also defined as the circumcenters of the triangles generated by a Delaunay triangulation.
So if we compute the Delaunay triangulation of the area, and their circumcenters
dt=delaunayTriangulation([x;y].');
cc=circumcenter(dt); %voronoi edges
And compute the distances between the circumcenters and any of the points that define each triangle:
for ii=1:size(cc,1)
if cc(ii,1)>0 && cc(ii,1)<5 && cc(ii,2)>0 && cc(ii,2)<5
point=dt.Points(dt.ConnectivityList(ii,1),:); %the first one, or any other (they are the same distance)
distance(ii)=sqrt((cc(ii,1)-point(1)).^2+(cc(ii,2)-point(2)).^2);
end
end
Then we have the center (cc) and radius (distance) of all possible circles that have no point inside them. We just need the biggest one!
[r,ind]=max(distance); %Tada!
Now lets plot
hold on
ang=0:0.01:2*pi;
xp=r*cos(ang);
yp=r*sin(ang);
point=cc(ind,:);
voronoi(x,y)
triplot(dt,'color','r','linestyle',':')
plot(point(1)+xp,point(2)+yp,'k');
plot(point(1),point(2),'g.','markersize',20);
Notice how the center of the circle is on one vertex of the Voronoi diagram.
NOTE: this will find the center inside [0-5],[0-5]. you can easily modify it to change this constrain. You can also try to find the circle that fits on its entirety inside the interested area (as opposed to just the center). This would require a small addition in the end where the maximum is obtained.
I'd like to propose another solution based on a grid search with refinement. It's not as advanced as Ander's or as short as rahnema1's, but it should be very easy to follow and understand. Also, it runs quite fast.
The algorithm contains several stages:
We generate an evenly-spaced grid.
We find the minimal distances of points in the grid to all provided points.
We discard all points whose distances are below a certain percentile (e.g. 95th).
We choose the region which contains the largest distance (this should contain the correct center if my initial grid is fine enough).
We create a new meshgrid around the chosen region and find distances again (this part is clearly sub-optimal, because the distances are computed to all points, including far and irrelevant ones).
We iterate the refinement within the region, while keeping an eye on the variance of the top 5% of values -> if it drops below some preset threshold we break.
Several notes:
I have made the assumption that circles cannot go beyond the scattered points' extent (i.e. the bounding square of the scatter acts as an "invisible wall").
The appropriate percentile depends on how fine the initial grid is. This will also affect the amount of while iterations, and the optimal initial value for cnt.
function [xBest,yBest,R] = q42806059
rng(1)
x=rand(1,100)*5;
y=rand(1,100)*5;
%% Find the approximate region(s) where there exists a point farthest from all the rest:
xExtent = linspace(min(x),max(x),numel(x));
yExtent = linspace(min(y),max(y),numel(y)).';
% Create a grid:
[XX,YY] = meshgrid(xExtent,yExtent);
% Compute pairwise distance from grid points to free points:
D = reshape(min(pdist2([XX(:),YY(:)],[x(:),y(:)]),[],2),size(XX));
% Intermediate plot:
% figure(); plot(x,y,'.k'); hold on; contour(XX,YY,D); axis square; grid on;
% Remove irrelevant candidates:
D(D<prctile(D(:),95)) = NaN;
D(D > xExtent | D > yExtent | D > yExtent(end)-yExtent | D > xExtent(end)-xExtent) = NaN;
%% Keep only the region with the largest distance
L = bwlabel(~isnan(D));
[~,I] = max(table2array(regionprops('table',L,D,'MaxIntensity')));
D(L~=I) = NaN;
% surf(XX,YY,D,'EdgeColor','interp','FaceColor','interp');
%% Iterate until sufficient precision:
xExtent = xExtent(~isnan(min(D,[],1,'omitnan')));
yExtent = yExtent(~isnan(min(D,[],2,'omitnan')));
cnt = 1; % increase or decrease according to the nature of the problem
while true
% Same ideas as above, so no explanations:
xExtent = linspace(xExtent(1),xExtent(end),20);
yExtent = linspace(yExtent(1),yExtent(end),20).';
[XX,YY] = meshgrid(xExtent,yExtent);
D = reshape(min(pdist2([XX(:),YY(:)],[x(:),y(:)]),[],2),size(XX));
D(D<prctile(D(:),95)) = NaN;
I = find(D == max(D(:)));
xBest = XX(I);
yBest = YY(I);
if nanvar(D(:)) < 1E-10 || cnt == 10
R = D(I);
break
end
xExtent = (1+[-1 +1]*10^-cnt)*xBest;
yExtent = (1+[-1 +1]*10^-cnt)*yBest;
cnt = cnt+1;
end
% Finally:
% rectangle('Position',[xBest-R,yBest-R,2*R,2*R],'Curvature',[1 1],'EdgeColor','r');
The result I'm getting for Ander's example data is [x,y,r] = [0.7832, 2.0694, 0.7815] (which is the same). The execution time is about half of Ander's solution.
Here are the intermediate plots:
Contour of the largest (clear) distance from a point to the set of all provided points:
After considering distance from the boundary, keeping only the top 5% of distant points, and considering only the region which contains the largest distance (the piece of surface represents the kept values):
And finally:
You can use bwdist from Image Processing Toolbox to compute the distance transform of the image. This can be regarded as a method to create voronoi diagram that well explained in #AnderBiguri's answer.
img = imread('AbmxL.jpg');
%convert the image to a binary image
points = img(:,:,3)<200;
%compute the distance transform of the binary image
dist = bwdist(points);
%find the circle that has maximum radius
radius = max(dist(:));
%find position of the circle
[x y] = find(dist == radius);
imshow(dist,[]);
hold on
plot(y,x,'ro');
The fact that this problem can be solved using a "direct search" (as can be seen in another answer) means one can look at this as a global optimization problem. There exist various ways to solve such problems, each appropriate for certain scenarios. Out of my personal curiosity I have decided to solve this using a genetic algorithm.
Generally speaking, such an algorithm requires us to think of the solution as a set of "genes" subject to "evolution" under a certain "fitness function". As it happens, it's quite easy to identify the genes and the fitness function in this problem:
Genes: x , y, r.
Fitness function: technically, maximum area of circle, but this is equivalent to the maximum r (or minimum -r, since the algorithm requires a function to minimize).
Special constraint - if r is larger than the euclidean distance to the closest of the provided points (that is, the circle contains a point), the organism "dies".
Below is a basic implementation of such an algorithm ("basic" because it's completely unoptimized, and there is lot of room for optimizationno pun intended in this problem).
function [x,y,r] = q42806059b(cloudOfPoints)
% Problem setup
if nargin == 0
rng(1)
cloudOfPoints = rand(100,2)*5; % equivalent to Ander's initialization.
end
%{
figure(); plot(cloudOfPoints(:,1),cloudOfPoints(:,2),'.w'); hold on; axis square;
set(gca,'Color','k'); plot(0.7832,2.0694,'ro'); plot(0.7832,2.0694,'r*');
%}
nVariables = 3;
options = optimoptions(#ga,'UseVectorized',true,'CreationFcn',#gacreationuniform,...
'PopulationSize',1000);
S = max(cloudOfPoints,[],1); L = min(cloudOfPoints,[],1); % Find geometric bounds:
% In R2017a: use [S,L] = bounds(cloudOfPoints,1);
% Here we also define distance-from-boundary constraints.
g = ga(#(g)vectorized_fitness(g,cloudOfPoints,[L;S]), nVariables,...
[],[], [],[], [L 0],[S min(S-L)], [], options);
x = g(1); y = g(2); r = g(3);
%{
plot(x,y,'ro'); plot(x,y,'r*');
rectangle('Position',[x-r,y-r,2*r,2*r],'Curvature',[1 1],'EdgeColor','r');
%}
function f = vectorized_fitness(genes,pts,extent)
% genes = [x,y,r]
% extent = [Xmin Ymin; Xmax Ymax]
% f, the fitness, is the largest radius.
f = min(pdist2(genes(:,1:2), pts, 'euclidean'), [], 2);
% Instant death if circle contains a point:
f( f < genes(:,3) ) = Inf;
% Instant death if circle is too close to boundary:
f( any( genes(:,3) > genes(:,1:2) - extent(1,:) | ...
genes(:,3) > extent(2,:) - genes(:,1:2), 2) ) = Inf;
% Note: this condition may possibly be specified using the A,b inputs of ga().
f(isfinite(f)) = -genes(isfinite(f),3);
%DEBUG:
%{
scatter(genes(:,1),genes(:,2),10 ,[0, .447, .741] ,'o'); % All
z = ~isfinite(f); scatter(genes(z,1),genes(z,2),30,'r','x'); % Killed
z = isfinite(f); scatter(genes(z,1),genes(z,2),30,'g','h'); % Surviving
[~,I] = sort(f); scatter(genes(I(1:5),1),genes(I(1:5),2),30,'y','p'); % Elite
%}
And here's a "time-lapse" plot of 47 generations of a typical run:
(Where blue points are the current generation, red crosses are "insta-killed" organisms, green hexagrams are the "non-insta-killed" organisms, and the red circle marks the destination).
I'm not used to image processing, so it's just an Idea:
Implement something like a gaussian filter (blur) which transforms each particle (pixels) to a round gradiant with r=image_size (all of them overlapping). This way, you should get a picture where the most white pixels should be the best results. Unfortunately, the demonstration in gimp failed because the extreme blurring made the dots disappearing.
Alternatively, you could incrementelly extend all existing pixels by marking all neighbour pixels in an area (example: r=4), the pixels left would be the same result (those with the biggest distance to any pixel)

Turning XY data into polygon, and then sorting them clockwise

I got data set (formed by sum of sub-sets, hence its unsorted) and Id like to turn it into polygon.
Is there a simple Matlab procedure that sorts/turns data set into polygon? The data form outline of a polygon, BUT they are NOT in correct order:
(to the left). The polygon must consist of ALL the points, and the lines CANT intersect.
Sadly the polygon is NOT convex, so convhull wont work :C
Thanks for any ideas, Ben
EDIT: heres a little example of what I need to do - I need to convert blue polygon into red one, so there are no intersections.
x1 = [0, 1, 2, 1, 2, 0]
x2 = [0, 1, 2, 2, 1, 0]
y1 = [2, 1, 3, 3, 1, 2]
y2 = [2, 1, 1, 3, 3, 2]
plot(x1,y1,'b-*')
axis([0,3,0,4])
pause
hold on, plot(x2,y2,'r-o')
EDIT 2: Ive finally managed to get rid of excess data, so here's the actual data Im trying to fit (blue points), data fit by matlab when using convhull to the left, and how its SUPPOSED to look, edited with green lines - to the right.
Ive tried looking for Hamiltonian path in Matlab but didnt find any direct commands, is there one for it?
And here's the data:
data1=[19.4500010000000 50500000;19.4500010000000 52810000;19.4500010000000 55200000;19.4599990000000 55200000;19.6900010000000 48800000;19.7910002000000 55200000;19.8560000000000 55200000;20.0100000000000 55200000;20.1500000000000 55200000;26.8099990000000 54700000;26.8099990000000 54700000;27.8300000000000 54500000;27.8300000000000 54500000;27.8300000000000 54500000;25.4047236012803 43066163.6552646;38.2799990000000 8420000;38.2799990000000 8420000;38.2799990000000 8420000;36.4199980000000 5270000;36.4199980000000 5270000;36.4199980000000 5270000;36.4199980000000 5270000;49.1845567757586 1577538.50621129;47.4100000000000 926524;47.4100000000000 926524;47.4100000000000 926524.000000004;47.4100000000000 926524;61.1736702657022 365441.704934877;58.3499980000000 230682;58.3499980000000 230682;71.8983466422650 108263.586243626;69.5500030000000 74543.3000000000;79.6100010000000 30424.7000000000;79.7029992000000 30424.7000000000;79.7699970000000 30424.7000000000;83.6800000000000 31281.3000000000;83.6800000000000 31693.1300000000;83.6800000000000 32131.1000000000]
c1=[1;5;19;24;29;32;33;34;35;36;37;38;12;11;9;8;7;6;4;3;2;1]
semilogy(data1(:,1),data1(:,2),'-*b')
hold on, semilogy(data1(c1,1),data1(c1,2),'r')
You can sort the points according to the angle with regard to the center of the points, as follows:
%Generate random example
n = 10;
x = rand(1,n);
y = rand(1,n);
%Find the order of the points
[~,porder] = sort(atan2(y-mean(y),x-mean(x)));
xsort = x(porder);
ysort = y(porder);
%Plot polygon
scatter(x,y);
hold on;
plot([xsort,xsort(1)],[ysort,ysort(1)]);
I have suggestion although I'm not 100% sure it will work for all possible collection of points.
Step1 : Start with a convex hull of the points and generate a polygon.
Step2 : Collect all the points which are not part of the convex hull.
Step3 : Then determine the shortest distance for each point to any segment of the convex hull polygon.
Step4: Pick the point with the smallest distance and split the segment that it is closest to, to pass through this point.
Step5: Repeat from step 2 until all points are included.

How to find intersections in binary image lines?

I have a binary image with curved lines as shown below, but I would like to know how I can find where they would intersect if they are extended.
So could you give me some ides on how i could:
extend the line endpoints in the same direction,
how to find the intersections?
I have thought about using hough transform to find lines, then intersection, but in some images my line endpoints are not exactly straight. Is there a way to maybe only find the direction of the line at the end of it instead of over the whole line, as it is a binary image?
Thanks for any help
Applying a dilation and then an erosion will extend your endpoints like this:
(*Code in Mathematica*)
Erosion[Dilation[i, 10], 10]
A full solution could be something like this:
r = Dilation[MorphologicalBranchPoints[
Thinning[Binarize#Erosion[Dilation[i, 10], 10], 10]] // Colorize, 3]
ImageAdd[i, r]
I think you should take a look at Hough transform. It calculates lines equations from binary reprentation (usually output of edge detector). Once you have this, it is a piece of cake to calculate intersections.
You could try to fit three corresponding curves and then solve the equation for the two intersections explicitely.
There exist some established models for curve fitting.
Here is what I came up with using Hough Transform:
%# read and binarize image
I = imread('http://i.stack.imgur.com/XlxmL.jpg');
BW = im2bw(rgb2gray(I));
%# hough transform, detect peaks, then get lines segments
[H T R] = hough(BW, 'Theta',-10:10); %# specific theta range
P = houghpeaks(H, 5);
lines = houghlines(BW, T, R, P);
%# overlay detected lines over image
figure, imshow(BW), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1), xy(:,2), 'g.-', 'LineWidth',2);
end
%# find endpoints (intersections) and show them
xy = [vertcat(lines.point1);vertcat(lines.point2)];
[~,idx1] = min(xy(:,2));
[~,idx2] = max(xy(:,2));
xy = xy([idx1;idx2],:); %# intersection points
plot(xy(:,1),xy(:,2), 'ro', 'LineWidth',3, 'MarkerSize',12)
hold off
Simply looking at your lines, they are more or less straight lines (not concave/convex curves) In my humble opinion, there's an easier way and more obvious way, since, you know either end points of the three lines. You can always get the intersection by solving x and y respectively.
http://zonalandeducation.com/mmts/intersections/intersectionOfTwoLines1/intersectionOfTwoLines1.html
gd luck
fill contours into std::vector<std::vector<cv::Point> > , using findContours function from OpenCV library, then for any two contours which don't intersect ( case of intersection i'll explane later) do the following:
first contour is the sequence of 2D points A1 A2 .... An and second contour is B1, B2, .., Bm, fix some i > 0 && i < n , j >0 && j < m and do extrapolation using (A1, ..., Ai) for finding extend from first endpoint of first contour than extrapolate (An-i, ... ,An) for finding extendion of the first contour from second endpoint: do this similarly for second contour (B1, ... ,Bj) &&(Bm-j, ... , Bm) :
now you can extend your contours till borders of image and check are their intersect or not.
i hope you know how to find intersection of the segments in 2D space. You must use this for all [Ai Ai+1] and [Bj Bj+1] i = 1,... ,n-1 && j = 1,...,m-1