Turning XY data into polygon, and then sorting them clockwise - matlab

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.

Related

What’s the most efficient way to find the coordinates of all internal edges of a 3D grid?

I need to find the coordinates of all the internal edges of an image. I have tried to achieve this with the following procedure:
Generate grid using pixel size of 0.5
Obtain coordinates of all vertices.
Remove all unwanted rows:
Rows with all integer values
Rows with 2 non-integers
Rows with all non-integers
Re-sample your grid using mesh size of 1 pixel.
I feel that resampling the grids with a pixel spacing of 1 will leave me with the coordinates obtained in step 3 as the coordinates of the edges.
The code is as follows:
% input image
Ydim = 3;
Xdim = 3;
Zdim = 3;
% generate 3D mesh using a pixel spacing of 0.5
[xgv, ygv, zgv] = meshgrid(1:0.5:Xdim - 1, 1:0.5:Ydim - 1, 1:0.5:Zdim - 1);
% obtain coordinates of all internal vertices and edges
allCoords = [ygv(:), xgv(:), zgv(:)];
% Obtain only the coordinates of edges by keeping only two integers and one
% non-integer in each row
edgeCoords = allCoords;
edgeCoords((sum(mod(allCoords,1)~=0, 2))~=1, :) = [];
% re-sample 3D grid using a pixel spacing of 1
[columnsInImage, rowsInImage, pagesInImage] = meshgrid(1:Xdim - 1, 1:Ydim - 1, 1:Zdim - 1);
% plot points
plot3(edgeCoords(:,2), edgeCoords(:,1), edgeCoords(:,3), '.b', 'markersize', 20)
hold on;
grid on;
scatter3(edgeCoords(:,1), edgeCoords(:,2), edgeCoords(:,3));
I am not exactly sure of the assumption in 5) above, as well as the overall procedure. Hence, I need someone to help me look at this. Is my assumption correct? Is there a more efficient way to do this?
Lastly, I would love to visualize this better than I already have in the code. Thanks for your help guys!

Test if points are within rectangles

I have some data points and can easily plot them in a figure in MATLAB.
I need to find out which data points are located inside some rectangular areas, as can be seen in the attached picture. In this picture, black dots represent my data points and red rectangles represent mentioned areas.
How can I search through my data points and see whether or not they belong to any of the rectangles? I need to have a list of all members (data points) for each rectangle.
Sample data points and rectangles:
As Ozcan said in the comments, inpolygon is the way to go. Here's a quick demo, see comments for details:
% Create 4 random rectangles, defined by their x and y coords in rectX and rectY.
% Each column defines a different rectangle.
sizes = randi([5,10], 2, 4)./10;
rectX = randi([1,5], 1, 4); rectX = [rectX; rectX; rectX + sizes(1,:); rectX + sizes(1,:)];
rectY = randi([1,5], 1, 4); rectY = [rectY; rectY + sizes(2,:); rectY + sizes(2,:); rectY];
% Create a random set of 1000 points for testing
points = [rand(1000, 1)*range(rectX(:))+min(rectX(:)), rand(1000, 1)*range(rectY(:))+min(rectY(:))];
% Set up logical matrix of test results
inrect = logical(zeros(size(points,1), size(rectX,2)));
% Plot the rectangles using patch
figure;
patch(rectX,rectY,'red')
% Hold on and plot all of the points as black dots
hold on;
plot(points(:,1),points(:,2),'.k');
% Loop through each rectangle, testing the points
for r = 1:size(rectX, 2)
% Test points using inpolygon, store results to inrect matrix
inrect(:,r) = inpolygon(points(:,1), points(:,2), rectX(:,r), rectY(:,r));
end
% Plot all points which are in any rectangle as blue circles
plot(points(any(inrect,2), 1), points(any(inrect,2), 2), 'bo');
Result:
Note you now have the logical matrix inrect, which is true (in one column per rectangle, one row per point) when the point is within a rectangle. The code above uses the any operator for plotting when the point is in any of the rectangles.

How to find the intersection of two ellipses in MATLAB

I have two equations:
ellipseOne = '((x-1)^2)/6^2 + y^2/3^2 = 1';
and
ellipseTwo = '((x+2)^2)/2^2 + ((y-5)^2)/4^2 = 1';
and I plotted them:
ezplot(ellipseOne, [-10, 10, -10, 10])
hold on
ezplot(ellipseTwo, [-10, 10, -10, 10])
title('Ellipses')
hold off
Now I'm trying to find the intersection of the two ellipses. I tried:
intersection = solve(ellipseOne, ellipseTwo)
intersection.x
intersection.y
to find the points where they intersect, but MATLAB is giving me a matrix and an equation as an answer which I don't understand. Could anyone point me in the right direction to get the coordinates of intersection?
The solution is in symbolic form. The last step you need to take is to transform it into numeric. Simply convert the result using double. However, because this is a pair of quadratic equations, there are 4 possible solutions due to the sign ambiguity (i.e. +/-) and can possibly give imaginary roots. Therefore, isolate out the real solutions and what is left should be your answer.
Therefore:
% Your code
ellipseOne = '((x-1)^2)/6^2 + y^2/3^2 = 1';
ellipseTwo = '((x+2)^2)/2^2 + ((y-5)^2)/4^2 = 1';
intersection = solve(ellipseOne, ellipseTwo);
% Find the points of intersection
X = double(intersection.x);
Y = double(intersection.y);
mask = ~any(imag(X), 2) | ~any(imag(Y), 2);
X = X(mask); Y = Y(mask);
The first three lines of code are what you did. The next four lines extract out the roots in numeric form, then I create a logical mask that isolates out only the points that are real. This looks at the imaginary portion of both the X and Y coordinate of all of the roots and if there is such a component for any of the roots, we want to eliminate those. We finally remove the roots that are imaginary and we should be left with two real roots.
We thus get for our intersection points:
>> disp([X Y])
-3.3574 2.0623
-0.2886 2.9300
The first column is the X coordinate and the second column is the Y coordinate. This also seems to agree with the plot. I'll take your ellipse plotting code and also insert the intersection points as blue dots using the above solution:
ezplot(ellipseOne, [-10, 10, -10, 10])
hold on
ezplot(ellipseTwo, [-10, 10, -10, 10])
% New - place intersection points
plot(X, Y, 'b.');
title('Ellipses');
hold off;

What is an simple way to compute the overlap between an image and a polygon?

I have a closed non-self-intersecting polygon. Its vertices are saved in two vectors X, and Y. Finally the values of X and Y are bound between 0 and 22.
I'd like to construct a matrix of size 22x22 and set the value of each bin equal to true if part of the polygon overlaps with that bin, otherwise false.
My initial thought was to generate a grid of points defined with [a, b] = meshgrid(1:22) and then to use inpolygon to determine which points of the grid were in the polygon.
[a b] = meshgrid(1:22);
inPoly1 = inpolygon(a,b,X,Y);
However this only returns true if if the center of the bin is contained in the polygon, ie it returns the red shape in the image below. However what need is more along the lines of the green shape (although its still an incomplete solution).
To get the green blob I performed four calls to inpolygon. For each comparison I shifted the grid of points either NE, NW, SE, or SW by 1/2. This is equivalent to testing if the corners of a bin are in the polygon.
inPoly2 = inpolygon(a-.5,b-.5,X,Y) | inpolygon(a+.5,b-.5,X,Y) | inpolygon(a-.5,b+5,X,Y) | inpolygon(a+.5,b+.5,X,Y);
While this does provide me with a partial solution it fails in the case when a vertex is contain in a bin but none of the bin corners are.
Is there a more direct way of attacking this problem, with preferably a solution that produces more readable code?
This plot was drawn with:
imagesc(inPoly1 + inPoly2); hold on;
line(a, b, 'w.');
line(X, Y, 'y);
One suggestion is to use the polybool function (not available in 2008b or earlier). It finds the intersection of two polygons and returns resulting vertices (or an empty vector if no vertices exist). To use it here, we iterate (using arrayfun) over all of the squares in your grid check to see whether the output argument to polybool is empty (e.g. no overlap).
N=22;
sqX = repmat([1:N]',1,N);
sqX = sqX(:);
sqY = repmat(1:N,N,1);
sqY = sqY(:);
intersects = arrayfun((#(xs,ys) ...
(~isempty(polybool('intersection',X,Y,[xs-1 xs-1 xs xs],[ys-1 ys ys ys-1])))),...
sqX,sqY);
intersects = reshape(intersects,22,22);
Here is the resulting image:
Code for plotting:
imagesc(.5:1:N-.5,.5:1:N-.5,intersects');
hold on;
plot(X,Y,'w');
for x = 1:N
plot([0 N],[x x],'-k');
plot([x x],[0 N],'-k');
end
hold off;
How about this pseudocode algorithm:
For each pair of points p1=p(i), p2=p(i+1), i = 1..n-1
Find the line passing through p1 and p2
Find every tile this line intersects // See note
Add intersecting tiles to the list of contained tiles
Find the red area using the centers of each tile, and add these to the list of contained tiles
Note: This line will take a tiny bit of effort to implement, but I think there is a fairly straightforward, well-known algorithm for it.
Also, if I was using .NET, I would simply define a rectangle corresponding to each grid tile, and then see which ones intersect the polygon. I don't know if checking intersection is easy in Matlab, however.
I would suggest using poly2mask in the Image Processing Toolbox, it does more or less what you want, I think, and also more or less what youself and Salain has suggested.
Slight improvement
Firstly, to simplify your "partial solution" - what you're doing is just looking at the corners. If instead of considering the 22x22 grid of points, you could consider the 23x23 grid of corners (which will be offset from the smaller grid by (-0.5, -0.5). Once you have that, you can mark the points on the 22x22 grid that have at least one corner in the polygon.
Full solution:
However, what you're really looking for is whether the polygon intersects with the 1x1 box surrounding each pixel. This doesn't necessarily include any of the corners, but it does require that the polygon intersects one of the four sides of the box.
One way you could find the pixels where the polygon intersects with the containing box is with the following algorithm:
For each pair of adjacent points in the polygon, calling them pA and pB:
Calculate rounded Y-values: Round(pA.y) and Round(pB.y)
For each horizontal pixel edge between these two values:
* Solve the simple linear equation to find out at what X-coordinate
the line between pA and pB crosses this edge
* Round the X-coordinate
* Use the rounded X-coordinate to mark the pixels above and below
where it crosses the edge
Do a similar thing for the other axis
So, for example, say we're looking at pA = (1, 1) and pB = (2, 3).
First, we calculated the rounded Y-values: 1 and 3.
Then, we look at the pixel edges between these values: y = 1.5 and y = 2.5 (pixel edges are half-offset from pixels
For each of these, we solve the linear equation to find where pA->pB intersects with our edges. This gives us: x = 1.25, y = 1.5, and x = 1.75, y = 2.5.
For each of these intersections, we take the rounded X-value, and use it to mark the pixels either side of the edge.
x = 1.25 is rounded to 1 (for the edge y = 1.5). We therefore can mark the pixels at (1, 1) and (1, 2) as part of our set.
x = 1.75 is rounded to 2 (for the edge y = 2.5). We therefore can mark the pixels at (2, 2) and (2, 3).
So that's the horizontal edges taken care of. Next, let's look at the vertical ones:
First we calculate the rounded X-values: 1 and 2
Then, we look at the pixel edges. Here, there is only one: x = 1.5.
For this edge, we find the where it meets the line pA->pB. This gives us x = 1.5, y = 2.
For this intersection, we take the rounded Y-value, and use it to mark pixels either side of the edge:
y = 2 is rounded to 2. We therefore can mark the pixels at (1, 2) and (2, 2).
Done!
Well, sort of. This will give you the edges, but it won't fill in the body of the polygon. However, you can just combine these with your previous (red) results to get the complete set.
First I define a low resolution circle for this example
X=11+cos(linspace(0,2*pi,10))*5;
Y=11+sin(linspace(0,2.01*pi,10))*5;
Like your example it fits with in a grid of ~22 units. Then, following your lead, we declare a meshgrid and check if points are in the polygon.
stepSize=0.1;
[a b] = meshgrid(1:stepSize:22);
inPoly1 = inpolygon(a,b,X,Y);
Only difference is that where your original solution took steps of one, this grid can take smaller steps. And finally, to include anything within the "edges" of the squares
inPolyFull=unique( round([a(inPoly1) b(inPoly1)]) ,'rows');
The round simply takes our high resolution grid and rounds the points appropriately to their nearest low resolution equivalents. We then remove all of the duplicates in a vector style or pair-wise fashion by calling unique with the 'rows' qualifier. And that's it
To view the result,
[aOrig bOrig] = meshgrid(1:22);
imagesc(1:stepSize:22,1:stepSize:22,inPoly1); hold on;
plot(X,Y,'y');
plot(aOrig,bOrig,'k.');
plot(inPolyFull(:,1),inPolyFull(:,2),'w.'); hold off;
Changing the stepSize has the expected effect of improving the result at the cost of speed and memory.
If you need the result to be in the same format as the inPoly2 in your example, you can use
inPoly2=zeros(22);
inPoly2(inPolyFull(:,1),inPolyFull(:,2))=1
Hope that helps. I can think of some other ways to go about it, but this seems like the most straightforward.
Well, I guess I am late, though strictly speaking the bounty time was till tomorrow ;). But here goes my attempt. First, a function that marks cells that contain/touch a point. Given a structured grid with spacing lx, ly, and a set of points with coordinates (Xp, Yp), set containing cells:
function cells = mark_cells(lx, ly, Xp, Yp, cells)
% Find cell numbers to which points belong.
% Search by subtracting point coordinates from
% grid coordinates and observing the sign of the result.
% Points lying on edges/grid points are assumed
% to belong to all surrounding cells.
sx=sign(bsxfun(#minus, lx, Xp'));
sy=sign(bsxfun(#minus, ly, Yp'));
cx=diff(sx, 1, 2);
cy=diff(sy, 1, 2);
% for every point, mark the surrounding cells
for i=1:size(cy, 1)
cells(find(cx(i,:)), find(cy(i,:)))=1;
end
end
Now, the rest of the code. For every segment in the polygon (you have to walk through the segments one by one), intersect the segment with the grid lines. Intersection is done carefully, for horizontal and vertical lines separately, using the given grid point coordinates to avoid numerical inaccuracies. For the found intersection points I call mark_cells to mark the surrounding cells to 1:
% example grid
nx=21;
ny=51;
lx = linspace(0, 1, nx);
ly = linspace(0, 1, ny);
dx=1/(nx-1);
dy=1/(ny-1);
cells = zeros(nx-1, ny-1);
% for every line in the polygon...
% Xp and Yp contain start-end points of a single segment
Xp = [0.15 0.61];
Yp = [0.1 0.78];
% line equation
slope = diff(Yp)/diff(Xp);
inter = Yp(1) - (slope*Xp(1));
if isinf(slope)
% SPECIAL CASE: vertical polygon segments
% intersect horizontal grid lines
ymax = 1+floor(max(Yp)/dy);
ymin = 1+ceil(min(Yp)/dy);
x=repmat(Xp(1), 1, ymax-ymin+1);
y=ly(ymin:ymax);
cells = mark_cells(lx, ly, x, y, cells);
else
% SPECIAL CASE: not horizontal polygon segments
if slope ~= 0
% intersect horizontal grid lines
ymax = 1+floor(max(Yp)/dy);
ymin = 1+ceil(min(Yp)/dy);
xmax = (ly(ymax)-inter)/slope;
xmin = (ly(ymin)-inter)/slope;
% interpolate in x...
x=linspace(xmin, xmax, ymax-ymin+1);
% use exact grid point y-coordinates!
y=ly(ymin:ymax);
cells = mark_cells(lx, ly, x, y, cells);
end
% intersect vertical grid lines
xmax = 1+floor(max(Xp)/dx);
xmin = 1+ceil(min(Xp)/dx);
% interpolate in y...
ymax = inter+slope*lx(xmax);
ymin = inter+slope*lx(xmin);
% use exact grid point x-coordinates!
x=lx(xmin:xmax);
y=linspace(ymin, ymax, xmax-xmin+1);
cells = mark_cells(lx, ly, x, y, cells);
end
Output for the example mesh/segment:
Walking through all polygon segments gives you the polygon 'halo'. Finally, the interior of the polygon is obtained using standard inpolygon function. Let me know if you need more details about the code.

Connect points and compute area

thats my first post, so please be kind.
I have a matrix with 3~10 coordinates and I want to connect these points to become a polygone with maximum size.
I tried fill() [1] to generate a plot but how do I calculate the area of this plot? Is there a way of converting the plot back to an matrix?
What would you reccomend me?
Thank you in advance!
[1]
x1 = [ 0.0, 0.5, 0.5 ];
y1 = [ 0.5, 0.5, 1.0 ];
fill ( x1, y1, 'r' );
[update]
Thank you for your answer MatlabDoug, but I think I did not formulate my question clear enough. I want to connect all of these points to become a polygone with maximum size.
Any new ideas?
x1 = rand(1,10)
y1 = rand(1,10)
vi = convhull(x1,y1)
polyarea(x1(vi),y1(vi))
fill ( x1(vi), y1(vi), 'r' );
hold on
plot(x1,y1,'.')
hold off
What is happening here is that CONVHULL is telling us which verticies (vi) are on the convex hull (the smallest polygon that encloses all the points). Knowing which ones are on the convex hull, we ask MATLAB for the area with POLYAREA.
Finally, we use your FILL command to draw the polygon, then PLOT to place the points on there for confirmation.
I second groovingandi's suggestion of trying all polygons; you just have to be sure to check the validity of the polygon (no self-intersections, etc).
Now, if you want to work with lots of points... As MatlabDoug pointed out, the convex hull is a good place to start. Notice that the convex hull gives a polygon whose area is the maximum possible. The problem, of course, is that there could be points in the interior of the hull that are not part of the polygon. I propose the following greedy algorithm, but I am not sure if it guarantees THE maximum area polygon.
The basic idea is to start with the convex hull as a candidate final polygon, and carve out triangles corresponding to the unused points until all the points belong to the final polygon. At each stage, the smallest possible triangle is removed.
Given: Points P = {p1, ... pN}, convex hull H = {h1, ..., hM}
where each h is a point that lies on the convex hull.
H is a subset of P, and it is also ordered such that adjacent
points in the list of H are edges of the convex hull, and the
first and last points form an edge.
Let Q = H
while(Q.size < P.size)
% For each point, compute minimum area triangle
T = empty heap of triangles with value of their area
For each P not in Q
For each edge E of Q
If triangle formed by P and E does not contain any other point
Add triangle(P,E) with value area(triangle(P,E))
% Modify the current polygon Q to carve out the triangle
Let t=(P,E) be the element of T with minimum area
Find the ordered pair of points that form the edge E within Q
(denote them Pa and Pb)
Replace the pair (Pa,Pb) with (Pa,E,Pb)
Now, in practice you don't need a heap for T, just append the data to four lists: one for P, one for Pa, one for Pb, and one for the area. To test if a point lies within a triangle, you only need to test each point against the lines forming the sides of the triangle, and you only need to test points not already in Q. Finally, to compute the area of the final polygon, you can triangulate it (like with the delaunay function, and sum up the areas of each triangle in the triangulation), or you can find the area of the convex hull, and subtract out the areas of the triangles as you carve them out.
Again, I don't know if this greedy algorithm is guaranteed to find the maximum area polygon, but I think it should work most of the time, and is interesting nonetheless.
You said you only have 3...10 points to connect. In this case, I suggest you just take all possible combinations, compute the areas with polyarea and take the biggest one.
Only if your number of points increases or if you have to compute it frequently so that compuation time matters, it's worth investing some time in a better algorithm. However I think it's difficult to come up with an algorithm and prove its completeness.
Finding the right order for the points is the hard part, as Amro commented. Does this function suffice?
function [idx] = Polyfy(x, y)
% [idx] = Polyfy(x, y)
% Given vectors x and y that contain pairs of points, find the order that
% joins them into a polygon. fill(x(idx),y(idx),'r') should show no holes.
%ensure column vectors
if (size(x,1) == 1)
x = x';
end
if (size(y,1) == 1)
y = y';
end
% vectors from centroid of points to each point
vx = x - mean(x);
vy = y - mean(y);
% unit vectors from centroid towards each point
v = (vx + 1i*vy)./abs(vx + 1i*vy);
vx = real(v);
vy = imag(v);
% rotate all unit vectors by first
rot = [vx(1) vy(1) ; -vy(1) vx(1)];
v = (rot*[vx vy]')';
% find angles from first vector to each vector
angles = atan2(v(:,2), v(:,1));
[angles, idx] = sort(angles);
end
The idea is to find the centroid of the points, then find vectors from the centroid to each point. You can think of these vectors as sides of triangles. The polygon is made up the set of triangles where each vector is used as the "left" and "right" only once, and no vectors are skipped. This boils down to ordering the vectors by angle around the centroid.
I chose to do this by normalizing the vectors to unit length, choosing one of them as a rotation vector, and rotating the rest. This allowed me to simply use atan2 to find the angles. There's probably a faster and/or more elegant way to do this, but I was confusing myself with trig identities. Finally, sorting those angles provides the correct order for the points to form the desired polygon.
This is the test function:
function [x, y] = TestPolyArea(N)
x = rand(N,1);
y = rand(N,1);
[indexes] = Polyfy(x, y);
x2 = x(indexes);
y2 = y(indexes);
a = polyarea(x2, y2);
disp(num2str(a));
fill(x2, y2, 'r');
hold on
plot(x2, y2, '.');
hold off
end
You can get some pretty wild pictures by passing N = 100 or so!