Connecting random points in MATLAB without intersecting lines - arrays

I need help with solving this problem. I have randomly generated points (example on Picture #1) and I want to connect them with lines (example on Picture #2). Lines can't be intersected and after connection, the connected points should look like an irregular area.
%Generating random points
xn = randi([3 7],1,10);
yn = randi([3 6],1,10);
%Generated points
xn = [6,3,7,7,6,6,6,4,6,3];
yn = [5,3,4,3,3,6,5,4,6,3];
Picture #1:
Result should be like this:
Picture #2:
Any idea how to solve this?

I suppose for the general case it can be very difficult to come up with a solution. But, assuming your points are scattered "nicely" there is quite a simple solution.
If you sort your points according to the angle above the x axis of the vector connecting the point and the center of the point cloud then:
P = [xn;yn]; %// group the points as columns in a matrix
c = mean(P,2); %// center point relative to which you compute the angles
d = bsxfun(#minus, P, c ); %// vectors connecting the central point and the dots
th = atan2(d(2,:),d(1,:)); %// angle above x axis
[st si] = sort(th);
sP = P(:,si); %// sorting the points
And that's about it. To plot the result:
sP = [sP sP(:,1)]; %// add the first point again to close the polygon
figure;plot( sP(1,:), sP(2,:), 'x-');axis([0 10 0 10]);
This algorithm will fail if several points has the same angle w.r.t the center of the point cloud.
An example with 20 random points:
P = rand(2,50);

You could adapt the code from another answer I gave for generating random simple polygons of an arbitrary number of sides. The difference here is you already have your set of points chosen and thus implicitly the number of sides you want (i.e. the same as the number of unique points). Here's what the code would look like:
xn = [6,3,7,7,6,6,6,4,6,3]; % Sample x points
yn = [5,3,4,3,3,6,5,4,6,3]; % Sample y points
[~, index] = unique([xn.' yn.'], 'rows', 'stable'); % Get the unique pairs of points
x = xn(index).';
y = yn(index).';
numSides = numel(index);
dt = DelaunayTri(x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
while numEdges ~= numSides
if numEdges > numSides
triIndex = vertexAttachments(dt, boundaryEdges(:,1));
triIndex = triIndex(randperm(numel(triIndex)));
keep = (cellfun('size', triIndex, 2) ~= 1);
end
if (numEdges < numSides) || all(keep)
triIndex = edgeAttachments(dt, boundaryEdges);
triIndex = triIndex(randperm(numel(triIndex)));
triPoints = dt([triIndex{:}], :);
keep = all(ismember(triPoints, boundaryEdges(:,1)), 2);
end
if all(keep)
warning('Couldn''t achieve desired number of sides!');
break
end
triPoints = dt.Triangulation;
triPoints(triIndex{find(~keep, 1)}, :) = [];
dt = TriRep(triPoints, x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
end
boundaryEdges = [boundaryEdges(:,1); boundaryEdges(1,1)];
x = dt.X(boundaryEdges, 1);
y = dt.X(boundaryEdges, 2);
And here's the resulting polygon:
patch(x,y,'w');
hold on;
plot(x,y,'r*');
axis([0 10 0 10]);
Two things to note:
Some sets of points (like the ones you chose here) will not have a unique solution. Notice how my code connected the top 4 points in a slightly different way than you did.
I made use of the TriRep and DelaunayTri classes, both of which may be removed in future MATLAB releases in favor of the delaunayTriangulation class.

Related

How to calculate coordinates of N equidistant points along a straight line between 2 coordinates on a map?

I have two points on a map -
val point1 : LatLng(13.3016139,77.4219107)
val point2 : LatLng(14.1788932,77.7613413)
I want to calculate and find 100 equidistant points along a straight line between these two coordinates. How do I do that?
ps. I'm sure this has been asked before, I just can't find it.
Equidistant, and more importantly, straight by which projection?
usually, to find a distance in cartesian space one would use something like the
Haversine formula to find a value, as previously answered in stack answer: How to convert latitude or longitude to meters?
As for the equidistant part, once you have the distance decided as per your taste of the shape and radius of Earth at given points, a simple division will do. .
python 3.7
>>> dist = 5427 #just some number
>>> nbr_o_points = 101
>>> points = [(dist/nbr_o_points)*(i+1) for i in range(nbr_o_points)]
>>> [f'{p:.2f}' for p in points]
['53.73', '107.47', '161.20',..., '5319.53', '5373.27', '5427.00']
Now to transfer these distances from point a to b back onto the desired projection... This is not part of your question... Stack - how-to-determine-vector-between-two-lat-lon-points might help.
take the vector and multiply by the dists in points in order to get your coordinates.
This is how I solved it -
fun findEquidistantPoints(latLng1: LatLng, latLng2: LatLng, pointCount: Int): ArrayList<LatLng> {
if (pointCount < 0)
throw IllegalArgumentException("PointCount cannot be less than 0")
val points = ArrayList<LatLng>()
val displacement = latLng1.displacementFromInMeters(latLng2)
val distanceBetweenPoints = displacement / (pointCount + 1)
for (i in 1..pointCount) {
val t = (distanceBetweenPoints * i) / displacement
points.add(LatLng(
(1 - t) * latLng1.latitude + t * latLng2.latitude,
(1 - t) * latLng1.longitude + t * latLng2.longitude
))
}
return points
}

Coordinates of dimension-wise maximum of Matlab array

I have 5-dimensional array of numbers. The goal is to find maximum values along 5-th dimension and their coordinates. I use
[x,y] = max(A,[],5);
Ideally I expect that x == A(y), however this does not appear to happen. I need an idea of how to translate y to an array of coordinates z such that x == A(z). Using find + loops is costly in my case, since matrices are huge.
Suppose your matrix A has dimension of (m,n,o). Now you have the indices of maximum entries along the 3rd dimension in y and the corresponding maximum values in x. You can access the maximum values by the following code-
z = (1:m*n)' + (y(:)-1)*(m*n); % linear index of these locations in full array
final_matrix = reshape(A(z),m,n);
It can be easily extended to 5 dimensional matrices.
Try this code for 5-dimensional-
[x,y] = max(A,[], 5);
z = (1:m*n*o*p)' + (y(:)-1)*(m*n*o*p);
final_matrix = reshape(A(z),m,n,o,p);
s = size(A);
[v,ii] = max(reshape(A,[],s(3)));
[i1 j1 ] = ind2sub(s(1:2),ii);
out = [v;i1;j1;1:s(3)]';

MATLAB Add Mouse Click Coordinate to Matrix?

I am creating an image processing project in matlab. I want to get 5 coordinates from image with mouse and save them to a matrix. When I run project, I click only once but the matrix is taking same coordinates. How can I fix it ?
function ImageClickCallback ( objectHandle , eventData )
array = 3:2;
for i = 1:3
axesHandle = get(objectHandle,'Parent');
coordinates = get(axesHandle,'CurrentPoint');
coordinates = coordinates(1,1:2);
array(i,1) = coordinates(1);
array(i,2) = coordinates(2);
end
disp(array);
For example when I click a point on image, I am taking this result. I can't select another points.
99.3806 37.1915
99.3806 37.1915
99.3806 37.1915
A much safer alternative would be to use ginput, with which you can select a variable number of points and store their coordinates easily. You don't need a loop; the coordinates are stored once all the points are selected.
Here is a simple example:
clear
clc
close all
A = imread('peppers.png');
imshow(A,[]);
hold on
%// Number of points
N = 5;
array = zeros(N,2);
%// Use a for loop and plot 1 point at a time.
for k = 1:N
[array(k,1),array(k,2)] = ginput(1);
%// Display the points
scatter(array(k,1),array(k,2),60,'k','filled')
end
Sample output for array:
123.0000 87.0000
95.0000 206.0000
256.0000 85.0000
236.0000 253.0000
395.0000 117.0000
And the image with the points displayed:
Therefore, you could would look like this:
function ImageClickCallback ( objectHandle , eventData )
array = zeros(3,2);
[array(:,1),array(:,2)] = ginput(3);

Store values from a time series function in an array using a for loop in R

I am working with Bank of America time series data for stock prices. I am trying to store the forecasted value for a specific step ahead (in this case 1:20 steps) in an array. I then need to subtract each value of the array from each value of the test array. Then I have to square each value of the array, sum all the squared values of the array, then divide by N (N = number of steps forecasted ahead).
I have the following so far. Also, the quantmod and fpp libraries are needed for this.
---------Bank of America----------
library(quantmod)
library(fpp)
BAC = getSymbols('BAC',from='2009-01-02',to='2014-10-15',auto.assign=FALSE)
BAC.adj = BAC$BAC.Adjusted
BAC.daily=dailyReturn(BAC.adj,type='log')
test = tail(BAC.daily, n = 20)
train = head(BAC.daily, n = 1437)
Trying to write a function to forecast, extract requisite value (point forecast for time i), then store it in an array where I can perform operations on that array (i.e. - add, multiply, exponentiate, sum the values of the array)
MSE = function(N){
for(i in 1:(N)){
x = forecast(model1, h = i)
y = x$mean
w = as.matrix(as.double(as.matrix(unclass(y))))
p = array(test[i,]-w[i,])
}
}
and we also have:
model1 = Arima(train, order = c(0,2,0))
MSE = function(N){
result = vector("list", length = (N))
for(i in 1:(N)){
x = forecast(model1, h = i)
point_forecast = as.double(as.matrix(unclass(x$mean)))
result[i] = point_forecast
}
result = as.matrix(do.call(cbind, result))
}
Neither of these functions have worked so far. When I run the MSE function, I get the following errors:
> MSE(20)
There were 19 warnings (use warnings() to see them)
> warnings()
Warning messages:
1: In result[i] = point_forecast :
number of items to replace is not a multiple of replacement length
2: In result[i] = point_forecast :
number of items to replace is not a multiple of replacement length
3: In result[i] = point_forecast :
number of items to replace is not a multiple of replacement length
4: In result[i] = point_forecast :
When I run MSE2 function, I get the following ouput:
MSE2(20)
[1] -0.15824
When putting a print statement inside, it printed out 'p' as a singular number, just like above (even though that had been run for i = 20). The x,y, and w variable in the MSE2 function act as vectors as far as storing the output, so I do not understand why p does not as well.
I appreciate any help in this matter, thank you.
Sincerely,
Mitchell Healy
Your question has two MSE functions: one in the first code block and one in the second code block.
Also, library(forecast) is needed to run Arima and forecast.
My understanding of what you are trying to do in the first paragraph is to compute the 20-step ahead forecast error. That is, what is the error in forecasts from model1 20 days ahead, based on your test data. This can be done in the code below:
model1 <- Arima(train, order = c(0,2,0))
y_fcst<-forecast(model1,h=20)$mean
errors<-as.vector(y_fcst)-as.vector(test)
MSE.fcst<-mean(errors^2)
However, I'm not sure what you're trying to do here: an ARIMA(0,2,0) model is simply modelling the differences in returns as a random walk. That is, this model just differences the returns twice and assumes this twice-differenced data is white noise. There's no parameters other than $\sigma^2$ being estimated.
Rob Hyndman has a blog post covering computing errors from rolling forecasts.
My solution to finding the MSE is below. I used log adjusted daily return data from Bank of America gathered through quantmod. Then I subsetted the data (which had length 1457) into training[1:1437] and testing[1438:1457].
The solution is:
forc = function(N){
forecast = matrix(data = NA, nrow = (N) )
for(i in 1:N){
fit = Arima(BAC.adj[(1+(i-1)):(1437+(i-1))], order = c(0,0,4))
x = forecast(fit, h = 1)
forecast[i,] = as.numeric(x$mean)
}
error = test - forecast
error_squared = error^2
sum_error_squared = sum(error_squared)
MSE = sum_error_squared/N
MSE
}

Surface area at certain distance from line collection in Matlab, similar to contour?

Dear stackoverflow users,
Some years ago i used mathematica for several months. After not programming for a few years I now do a research project, as a student, in which I use Matlab. I have found a lot of good help here on stackoverflow but now i am stuck at the following problem:
I have a data set of connections between nodes on a rectangular grid, each node has a possible connection to its 8 neighbors. My measurements are in the form of a 3 by n matrix where the first two values designate a node and the third value designates whether or not they are connected, the size of the grid is predetermined. Typically there are about ten lines coming from two or three nodes which are neighboring at least one of each other. The goal of my research project is to calculate the area at distance r around this collection of lines.
So far I have been able to plot the lines with the code below, for which I used bits of code from right here on stackoverflow, which was extremely useful. However I cant get a contour line around it at a certain distance (with which I would hope to calculate the area inside this contour line). The gplot function returns two vectors with two coordinates per line which I find difficult to convert to something more useable. I tried defining a value Z at a distance from the lines, to decline with distance from the lines, so I get a slope coming from these lines. From this slope i could calculate contourlines. However, because the lines are just coordinates I dont know how to calculate the distance to that line, opposed to when they would have been functions.
I am really at a loss. I hope I have somewhat clearly posted my problem here. This is the second time I post this problem, I have now added comments to the code and pictures to explain myself better. Thanks for any advice given!
This I have so far, the xls file is the 3 by n matrix i mention above, I have also written its contents in matrix form in the code below so my problem is easier to understand:
%# here i set my data/constants
filename='random.xls'; file=xlsread(filename); y=width; x=length;
%# random.xls looks approximately like this, after xlsread(filename) you get
file=[21 22 1;
21 20 1;
15 16 1;
15 14 1;
15 23 1;
14 22 1;
14 21 1;
22 15 1;
23 14 1;
24 15 1;
6 15 1;
5 14 1;
7 14 1;
8 15 1];
%# predefined width and length, i usually get this from the file
width=8; length=4;
%# here i create my adjaceny matrix in a elegant way user amro posted on stackoverflow
%# however i immediately multiply it by 0, creating a y*x by y*x matrix with all zeroes
[X Y] = meshgrid(1:x,1:y); X = X(:); Y = Y(:);
adjacency = squareform( pdist([X Y], 'chebychev') == 1 ); adjacency=adjacency*0;
%# here i take the matrix "file" for which the first two values are node numbers and
%# the third value designates whether there is a connection between the two nodes to
%# fill in the connections in the adjacencymatrix
[nrows,ncols]=size(file);
for r = 1:nrows
if file(r,3)==1
adjacency(file(r,1),file(r,2))=1;
end
end
adjacency=(adjacency+adjacency.');
%# plots the adjacencymatrix
subplot(121), spy(adjacency)
%# plots the connections and designates the nodes, note that the numbers designating
%# the nodes do not match original data, this is a separate problem i have not solved
[xx yy] = gplot(adjacency, [X Y]);
subplot(122), plot(xx, yy, 'ks-', 'MarkerFaceColor','b')
%# these last lines of code for plotting the numbers of the grid i do not fully
%# understand, in here is the cause for the numbers not matching the original data
axis([0 x+1 0 y+1])
[X Y] = meshgrid(1:x,1:y);
X = reshape(X',[],1) + 0.1; Y = reshape(Y',[],1) + 0.1;
text(X, Y(end:-1:1), cellstr(num2str((1:x*y)')) )
xlabel('length')
ylabel('width')
title(filename)
to clarify my problem i added these two pictures:
current plot http://imgur.com/5uPd4
area i want to know http://imgur.com/WsIbg
Solution to finding surface area inside isoline or contourline at distance r from collection of lines in Matlab, approximation by graphical processing (dilating), not an exact or efficient awnser!
I have made an approximation, so this is not an exact awnser nor is it efficient coding. A friend of mine who studies machine vision suggested converting the lines to pixels and then dilating the image with a disk, after which the pixel count is a measure of surface area:
%# constants and variables
minx = min(xx);
miny = min(yy);
maxx = max(xx);
maxy = max(yy);
rangex = maxx - minx;
rangey = maxy - miny;
borderRelNum = sqrt(2);
electrodeToImageScaleFactor = 100;
imsizex = 2*(maxx+borderRelNum)*electrodeToImageScaleFactor+2;
imsizey = 2*(maxy+borderRelNum)*electrodeToImageScaleFactor+2;
im = zeros(imsizex, imsizey);
grayscalevalue = 255;
disksize = round(borderRelNum*electrodeToImageScaleFactor);
%# transformation matrices
centerElectrodeSpace = [1, 0, -(minx + maxx) / 2;
0, 1, -(miny + maxy) / 2;
0, 0, 1 ];
scaleElectrodeToImage = [electrodeToImageScaleFactor , 0, 0;
0, electrodeToImageScaleFactor , 0;
0, 0, 1 ];
centerImageSpace = [ 1, 0, imsizex / 2;
0, 1, imsizey / 2;
0, 0, 1 ];
electrodeToImage = centerImageSpace * scaleElectrodeToImage * centerElectrodeSpace;
%# transformation
for i = 0:(size(xx,1) / 3 - 1)
p1 = [xx(i*3 + 1); yy(i*3 + 1); 1];
p2 = [xx(i*3 + 2); yy(i*3 + 2); 1];
p1im = electrodeToImage * p1
p2im = electrodeToImage * p2
lx = linspace( min( p1im(1), p2im(1) ), max( p1im(1), p2im(1) ), borderRelNum*electrodeToImageScaleFactor )
ly = linspace( min( p1im(2), p2im(2) ), max( p1im(2), p2im(2) ), borderRelNum*electrodeToImageScaleFactor )
index = sub2ind(size(im),round(lx),round(ly));
im(index) = grayscalevalue;
end
%# Now dilate and count pixels
se = strel('disk', disksize, 0);
im = imdilate(im, se);
image(im)
colormap(gray)
sum(sum(im/grayscalevalue))*(1/electrodeToImageScaleFactor^2)
If someone is able to solve my problem more elegantly, efficiently or more precisely i would still very much appreciate it. But this will do for now.
-edit- ok this is VERY inefficient indeed, my pc has been crunching numbers for 30 minutes on my data set (10 xls files, not that much) now and is still at file 1 it seems if i look at workspace values

Resources