How to expand/shrink 3D Polygon in 2D directions (X-Y)?

I have a xyz=17x3 array which forms an open square shape. I want to expand the shape (inside or outside only) with respect to xy_directions only and get a new array xy=17x2 . So I can add the third column (Z) to the new array xy from the original array xyz and end up with a third array XYZ1=17x3. where * XYZ1=[xy(:,1),xy(:,2),xyz(:,3)]*. In this case, I end up with expanded shape in xy_directions but keep (Z) fixed.(which I'm wishing for)
I tried the function expandPolygon from geom2d. But the output array has some rows filled with (Inf) instead of numbers, even though it has the same length as original array xyz.
Hope you can help me with that Thank you so much.

Risposte (3)

Matt J
Matt J il 10 Dic 2017
Modificato: Matt J il 10 Dic 2017
I may not fully understand the question. You have a square floating in 3D space. You want to expand or contract the square within the same plane that it exists now? If so, then you can simply do (assuming you have R2016b or higher) as follows:
xyz_new= c*(xyz-mean(xyz))+mean(xyz);
where c is an expansion or contraction factor. For example, with c=1.5, you would get the orange dots below.

11 Commenti

Faez Alkadi
Faez Alkadi il 10 Dic 2017
Modificato: Faez Alkadi il 10 Dic 2017
Hi Matt,
This solution works for simple shapes. But what if xyz=[1 1 5;1 5 5;2 5 5;2 1.5 5;3 1.5 5;3 5 5;4 5 5;4 1 5;2 1.5 5];
Can we offset it to inside or outside?
Thank you so much
Sorry, I don't understand what "offset" means here. Why doesn't my answer apply to this alternative xyz?
Faez Alkadi
Faez Alkadi il 10 Dic 2017
Modificato: Faez Alkadi il 10 Dic 2017
Sorry i meant expansion to outside or inside. The thing is if I apply your code on this xyz=[1 1;1 5 ;2 5 ;2 1.5 ;3 1.5 ;3 5 ;4 5 ;4 0.9;1.5 0.9]; We will get orange line in picture#1.
But i'm actually looking for something like orange line in picture#2.
By the way. This line was from function expandPolygon in geom2d by David Legland. as in link attached. The problem with this function is that it returns array with (Inf) in some rows if the data points are parallel. to see that use this xyz=[1 1;1 5 ;2 5 ;2 1.5 ;3 1.5 ;3 5 ;4 5 ;4 1;1.5 1]; you will get polyOut{1,1} containing (Inf) rows because last data point is parallel with first.
Thank you so much
Matt J
Matt J il 10 Dic 2017
Modificato: Matt J il 10 Dic 2017
Can't you just remove the redundant data point [1.5,1]?
Faez commented:
Even if I remove it. It won't work with the code you suggested.
My point was that if you remove it, maybe expandPolygon will work as intended.
It would effect the accuracy of my data in Z-direction
I don't see how.
Well, when i get polyOut,it will be Nx2 array. But it will contain (Inf) in it, so i won't be able to add the third column (Z) to it. It won't be able to be plotted. I can't have (Inf) in my final array. It won't work for my application
But if you remove the redundant point, why would you get Inf in the array at all?
I won't get get Inf in the array if i remove it.
But, the thing is i can't remove it. Because it might be parallel in X or Y but Z is changing. So if I remove it I would lose accuracy. this data here is just an example where Z is fixed. But I have other data where Z is changing.

Accedi per commentare.

Matt J
Matt J il 11 Dic 2017
Modificato: Matt J il 11 Dic 2017
To map everything into 2D
mu=mean(xyz);
xyzc=xyz-mu;
[~,~,V]=svd(xyzc, 0);
xy=xyzc*V(:,1:2);
Now you can use the geom2D toolkit freely on the 2D data set, xy to generate xy2. As we've discussed, remove redundant colinear points to avoid Infs. To map xy2 back to the original 3D coordinate system,
XYZ1= xy2 * V(:,1:2).' + mu ;

3 Commenti

Hello Matt,
I wasn't sure how to remove redundant colinear points. So I did the following, But I got the expansion in the picture. I think there is something wrong with the coordinates. I'm attaching xyz(Original) and xy2 (I got from geom2D toolkit after applying your code). I don't know if my way to remove redundant points was good.
Hope you can take a look and help to solve the problem.
Thank you so much for the help!
load xyz
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'*-')
mu=mean(xyz);
xyzc=xyz-mu;
[~,~,V]=svd(xyzc, 0);
xy=xyzc*V(:,1:2);
xy2 = expandPolygon(xy,0.5);
xy2=xy2{1,1};
ind = find(isfinite(xy2(:,1)));
[row col] = ind2sub(size(xy2), ind);
xy22=[xy2(row,1),xy2(row,2)];
XYZ1= xy22 * V(:,1:2).' + mu ;
hold on
plot3(XYZ1(:,1),XYZ1(:,2),XYZ1(:,3),'+-')
xlabel('X')
ylabel('Y')
zlabel('Z')
Sorry, I didn't know your xyz could be non-planar. Why don't you just apply expandPolygon to xyz(:,1:2), i.e., the 2D projection of the shape onto the x-y plane?
i actually don't know how to do that. Can you help ?

Accedi per commentare.

Matt J
Matt J il 13 Dic 2017
Modificato: Matt J il 13 Dic 2017
The attached file might be close to what you want. When I do
XYZ1=expandShape(xyz,0.1);
on your last xyz data set, I get the orange dots below,

3 Commenti

Hi Matt, First of all, thank you for your great effort.
I tried the function for different data set (attached) but it didNOT work well as shown in the pictures.
<<
>>
Matt J
Matt J il 5 Apr 2018
Modificato: Matt J il 5 Apr 2018
For such a highly non-planar shape, it is no longer clear how to define its expansion (which is why you might get unexpected results). In your previous examples, the points were all largely "piece-wise planar" and so the plane in which to expand the shape locally was pretty much unambiguous.
you are right, That's why i tried to use the function expandPolygon from the toolbox geom2d for X and Y and then was planning to add Z after i get the expanded resutlt for X and y. But the result for (XY-NEW) had a different size than (XY), it wasn't able to mach with Z.

Accedi per commentare.

Richiesto:

il 10 Dic 2017

Modificato:

il 7 Apr 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by