Create new isosurface from a isosurface

9 Ansichten (letzte 30 Tage)
Luigi
Luigi am 27 Mär. 2015
Beantwortet: Luigi am 7 Apr. 2015
Hi to everybody.
I have an isosurface, generated with isosurface function, so I have a struct in my workspace as follow
surface
tri: [93372x3 int32]
vert: [47915x3 single]
when I plot it I have the results showed in attacched image.
Now, I want to select a subset of points of isosurface and generate a new isosurface starting from this selected points.
For example, I want to extract from the isosurface only the points included inside the red circle, selecting with datacursor the center of each black dot and creating a new isosurface starting from the coordinates of each black dot.
I hope it's clear and that you can help me.
Thanks in advance
Best regards
Luigi

Antworten (7)

Mike Garrity
Mike Garrity am 27 Mär. 2015
The simplest way is the following.
Let's start with a really simple example:
[x y z v] = flow;
q = z./x.*y.^3;
p = patch(isosurface(x, y, z, q, -.08, v));
p.FaceColor = 'yellow';
view(3)
I want to keep everything between X=2 and X=4.
minx = 2;
maxx = 4;
inverts = p.Vertices(:,1) >= minx & p.Vertices(:,1) <= maxx;
The variable inverts is now a mask that is the size of my Vertices array and has a true for each vertex that I want to keep. Now I need to turn that into a mask of the faces I want to keep. To do that, I need to look at each column of the Faces array:
infaces = inverts(p.Faces(:,1)) & inverts(p.Faces(:,2)) & inverts(p.Faces(:,3));
Now infaces is a mask that is the size of my Faces array and has a true for every face where all three vertices have trues in inverts. Now we can use that to shrink the Faces array.
p.Faces = p.Faces(infaces,:);
The one problem with this approach is that the patch's Vertices array still contains all of those vertices that have been excluded. That's generally OK, but you might want to get rid of them. The problem is that to do that, you need to translate all of the indices in the Faces array from indices in the old, big Vertices array into indices into the new, small Vertices array. That's a messy bit of bookkeeping.

Luigi
Luigi am 31 Mär. 2015
Thank you so much.
Now I'm trying to translate all indices in the Faces array, It's a big mess!
  2 Kommentare
Mike Garrity
Mike Garrity am 31 Mär. 2015
I warned you!
It's actually not as bad as it looks at first. There are a couple of ways to do it. One of the simplest involves find:
%%Throw out unused verts & faces
new_verts = p.Vertices(inverts,:);
new_faces = p.Faces(infaces,:);
%%Fix faces
n2o = find(inverts);
for i=1:numel(new_faces)
new_faces(i) = find(n2o==new_faces(i));
end
I think that this can be improved in terms performance and robustness, but it doesn't need to get a lot uglier than this.
Luigi
Luigi am 31 Mär. 2015
Thank you so much Mike, I'll try and I'll let you know

Melden Sie sich an, um zu kommentieren.


Luigi
Luigi am 1 Apr. 2015
Hi Mike,
I've tried, It works!
Thank you so much for your help
Best regards
Luigi

Luigi
Luigi am 2 Apr. 2015
Hi Mark,
another question:
I would like to keep everything between (minx,maxx), (miny,maxy), (minz,maxz)
I've tried this code
_ _inverts = (p.Vertices(:,1) >= minx & p.Vertices(:,1) <= maxx) & (p.Vertices(:,2) >= miny & p.Vertices(:,2) <= maxy) & (p.Vertices(:,3) >= minz & p.Vertices(:,3) <= maxz);
infaces = inverts(p.Faces(:,1)) & inverts(p.Faces(:,2)) & inverts(p.Faces(:,3));
new_verts = p.Vertices(inverts,:);
new_faces = p.Faces(infaces,:);
n2o = find(inverts);
for i=1:numel(new_faces) new_faces(i) = find(n2o==new_faces(i)); end
but it doesn't work.
Where is my fault?
Thank you so much in advance
Best regards
Luigi
  1 Kommentar
Mike Garrity
Mike Garrity am 2 Apr. 2015
I'm not sure. If I assemble all the bits from this thread, I get this:
[x y z v] = flow;
q = z./x.*y.^3;
p = patch(isosurface(x, y, z, q, -.08, v));
p.FaceColor = 'yellow';
view(3)
minx = 2;
maxx = 8;
miny = -3;
maxy = 3;
minz = 0;
maxz = 3;
inverts = (p.Vertices(:,1) >= minx & p.Vertices(:,1) <= maxx) ...
& (p.Vertices(:,2) >= miny & p.Vertices(:,2) <= maxy) ...
& (p.Vertices(:,3) >= minz & p.Vertices(:,3) <= maxz);
infaces = inverts(p.Faces(:,1)) & inverts(p.Faces(:,2)) & inverts(p.Faces(:,3));
new_verts = p.Vertices(inverts,:);
new_faces = p.Faces(infaces,:);
n2o = find(inverts);
for i=1:numel(new_faces)
new_faces(i) = find(n2o==new_faces(i));
end
patch('Faces',new_faces,'Vertices',new_verts,'FaceColor','green')
If I run it, I get the following picture:
Is that what you get? How does it differ from what you expected?

Melden Sie sich an, um zu kommentieren.


Luigi
Luigi am 3 Apr. 2015
Hi Mike
I've tried your code, but I get this error
??? Warning: Struct field assignment overwrites a value with class "double". See MATLAB 7.0.4 Release Notes, Assigning Nonstructure Variables As Structures Displays Warning for details. Reference to non-existent field 'Vertices'.
and the image attached
I've modified my code that is the following :
Surface = load 'surface.mat';
xmin=-28; xmax=-50;
ymin=-12; ymax=-14;
zmin=20; zmax=100;
inverts = (surface.vert(:,1) >= xmin & surface.vert(:,1) <= xmax) & (surface.vert(:,2) >= ymin & surface.vert(:,2) <= ymax) & (surface.vert(:,3) >= zmin & surface.vert(:,3) <= zmax);
infaces = inverts(surface.tri(:,1)) & inverts(surface.tri(:,2)) & inverts(surface.tri(:,3));
surface.vert = surface.vert(inverts,:); surface.tri = surface.tri(infaces,:);
n2o = find(inverts); for i=1:numel(surface.tri) surface.tri(i) = find(n2o==surface.tri(i)); end
handle=trisurf(surface.tri, surface.vert(:, 1), surface.vert(:, 2), surface.vert(:, 3));
where surface is a struct
tri: [40772x3 int32] vert: [20864x3 single]
but, when I do this
surface.vert = surface.vert(inverts,:); surface.tri = surface.tri(infaces,:);
my surface becomes empty
tri: [0x3 int32] vert: [0x3 single]
Any suggest?
Thank you so much
regards
Luigi
  1 Kommentar
Mike Garrity
Mike Garrity am 3 Apr. 2015
Sorry, the error you hit running my code is because I'm using a syntax that was introduced in R2014b. I think you're running an older version.
In R2014b, the following are equivalent:
set(p,'FaceColor','yellow')
p.FaceColor = 'yellow'
But only the first worked in earlier versions. It's pretty simple to convert between the two forms, but that line that sets inverts would need a temp variable:
v = get(p,'Vertices');
inverts = (v(:,1) >= minx & v(:,1) <= maxx) ...
& (v(:,2) >= miny & v(:,2) <= maxy) ...
& (v(:,3) >= minz & v(:,3) <= maxz);
But I don't think that's the problem you've hit. At the point where you did this:
surface.vert = surface.vert(inverts,:);
surface.tri = surface.tri(infaces,:);
what do the variables inverts & infaces look like? In my example, they look like this:
>> any(inverts)
ans =
1
>> length(inverts)
ans =
2318
>> sum(inverts)
ans =
688
>> any(infaces)
ans =
1
>> length(infaces)
ans =
4344
>> sum(infaces)
ans =
1271
That's saying that I've selected 688 out of 2318 vertices and 1271 out of 4344 triangles.

Melden Sie sich an, um zu kommentieren.


Luigi
Luigi am 7 Apr. 2015
Hi Mike, thank you so much for your help.
In my case, variables look like :
any(inverts)
ans =
0
>> length(inverts)
ans =
20864
>> sum(inverts)
ans =
0
>> any(infaces)
ans =
0
>> length(infaces)
ans =
40772
>> sum(infaces)
ans =
0
this is the reason why I get them empty after the execution of the script.
I've tried also to create a temp variable for vertices, but I get the same result
Thank you so much
Regards
Luigi

Luigi
Luigi am 7 Apr. 2015
Problem solved!
It was my stupid mistake!
Because I assigned to xmin the value of xmax, i.e. I've assigned -12 to xmin e -50 to xmax, so that I get always empty ,trix!
thank you so much for your help
Best regards
Luigi

Community Treasure Hunt

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

Start Hunting!

Translated by