Thread Subject: Slice plane through a 3D object?

Subject: Slice plane through a 3D object?

From: Molly Dickens

Date: 7 Nov, 2001 22:30:24

Message: 1 of 3

I have a triangulated object in 3D (i.e. a surface made up of
 triangles). The handle to this object is a vector of handles to the
 individual patch objects (triangles).
 

 I want to be able to take a slice plane through this object. In
 other words, for a given plane in the 3D space, I want to obtain the
 polygon that is the intersection of that plane and my object.
 

 The function 'slice' can be used to produce a slice plane when you
 have volumetric data (3D matrix of values). But I don't have that
 and don't know how to convert what I have to a volume (i.e. voxelize).
 

 Any suggestions?!
 Thanks,
 Molly

Subject: Slice plane through a 3D object?

From: John D'Errico

Date: 8 Nov, 2001 09:18:34

Message: 2 of 3

This is fairly easy. We need not even assume that the
object is convex.

Assume your plane is represented as a point on the
plane (P0) and a normal vector (P1) to the plane,
and that P0 and P1 are (1x3) row vectors. I'll
also assume that you have the set of points on
which the triangulation is based in the (nx3)
array XYZ. Finally, I'll assume the triangulation
itself is an (mx3) integer array of indexes into
the rows of XYZ. Call it TRI.

% ============ begin matlab code ============
% first, determine which triangles cross the plane.
% vertex 1 of each triangle is:
a = XYZ(tri(:,1),:);
% likewise for vertex 2 and 3
b = XYZ(tri(:,2),:);
c = XYZ(tri(:,3),:);

% on which side of the plane are each of a,b,c?
% use a dot product (either the function dot or a
% matrix multiply will do
da=(a-repmat(p0,m,1)*p1';
db=(b-repmat(p0,m,1)*p1';
dc=(c-repmat(p0,m,1)*p1';

% if exactly 1 or 2 of the corners are on the
% "positive" side of the plane, then this face
% crosses the plane. k will be a list of the
% triangles the plane crosses
k=(da>0)+(db>0)+(dc>0);
k=find((k==1)|(k==2));

% if k is not empty, then the plane had some
% intersection with the object. I'll be lazy here
% and loop over the faces crossed, although the
% loop is easily vectorized
edgelist=[];
xyzp=[];
j=0;
for i=k
  edgei=[];
  % did we cross edge ab?
  if (da(i)*db(i))<=0
    j=j+1;
    edgei=j;
    t=abs(da(i))/(abs(da(i))+abs(db(i)));
    xyz0=XYZ(i,1)*(1-t)+XYZ(i,2)*t;
    xyzp=[xyzp;xyz0];
  end
  % did we cross edge ac?
  if (da(i)*dc(i))<=0
    j=j+1;
    edgei=[edgei,j];
    t=abs(da(i))/(abs(da(i))+abs(dc(i)));
    xyz0=XYZ(i,1)*(1-t)+XYZ(i,3)*t;
    xyzp=[xyzp;xyz0];
  end
  % did we cross edge bc?
  if (db(i)*dc(i))<=0
    j=j+1;
    edgei=[edgei,j];
    t=abs(db(i))/(abs(db(i))+abs(dc(i)));
    xyz0=XYZ(i,2)*(1-t)+XYZ(i,3)*t;
    xyzp=[xyzp;xyz0];
  end
  
  edgelist=[edgelist;edgei];
  
end
% ============ end matlab code ============

Edgelist is a list of pairs of endpoints of
line segments in the slice plane. It refers to
rows of the array xyzp. These edges are in no
special order.

I appologize if there are bugs in this code. I
have not tested it in matlab. You should be able
to figure out what I am doing however and fix
any bugs.

HTH,
John D'Errico



In article <eea741b.-1@WebX.raydaftYaTP>, "Molly Dickens"
<mdickens@coe.ttu.edu> wrote:

> I have a triangulated object in 3D (i.e. a surface made up of
> triangles). The handle to this object is a vector of handles to the
> individual patch objects (triangles).
>
>
> I want to be able to take a slice plane through this object. In
> other words, for a given plane in the 3D space, I want to obtain the
> polygon that is the intersection of that plane and my object.
>
>
> The function 'slice' can be used to produce a slice plane when you
> have volumetric data (3D matrix of values). But I don't have that
> and don't know how to convert what I have to a volume (i.e. voxelize).
>
>
> Any suggestions?!
> Thanks,
> Molly

--

Subject: Slice plane through a 3D object?

From: Sreerup

Date: 7 Oct, 2010 10:29:04

Message: 3 of 3


Hi John,
           Thanks for the code. I tried to use it in matlab platform and found little bugs. Here is the bug-free version ready to use in matlab.

Regards,

Sreerup

function [xyzp,edgelist]=slice_iso_data(p0,p1,XYZ,tri)

% Algorithm by: John D'Errico
% http://www.mathworks.cn/matlabcentral/newsreader/view_thread/29075

% Inputs:
% p0: point on the slice plane
% p1: normal vector to the slice plane
% p0 and p1 are (1x3) row vectors.
% XYZ: (nx3) array of vertices of isosurface data
% TRI: (mx3) integer array of connectivity matrix

% Outputs:
% Edgelist: list of pairs of endpoints of line segments in the slice plane.
% It refers to rows of the array xyzp. These edges are in no special order.

% -------------------------------------------------------------------------

% first, determine which triangles cross the plane.

% vertices 1, 2 and 3 of each triangle are:

a = XYZ(tri(:,1),:);
b = XYZ(tri(:,2),:);
c = XYZ(tri(:,3),:);

% on which side of the plane are each of a,b,c?
% use a dot product (either the function dot or a matrix multiply will do)

a=array_subs(a,p0);
b=array_subs(b,p0);
c=array_subs(c,p0);

da=a*p1';
db=b*p1';
dc=c*p1';

% if exactly 1 or 2 of the corners are on the "positive" side of the plane,
% then this face crosses the plane. k will be a list of the triangles the plane
% crosses.

k=(da>0)+(db>0)+(dc>0);
k=find((k==1)|(k==2));

% if k is not empty, then the plane had some intersection with the object.
% I'll be lazy here and loop over the faces crossed, although the loop is
% easily vectorized.

edgelist=[];
xyzp=[];
j=0;

for i=k(1):k(end)
    edgei=[];

    % did we cross edge ab?
    if (da(i)*db(i))<=0
        j=j+1;
        edgei=j;
        t=abs(da(i))/(abs(da(i))+abs(db(i)));
        xyz0=[XYZ(tri(i,1),:).*(1-t)+XYZ(tri(i,2),:).*t];
        xyzp=[xyzp;xyz0];
    end

    % did we cross edge ac?
    if (da(i)*dc(i))<=0
        j=j+1;
        edgei=[edgei,j];
        t=abs(da(i))/(abs(da(i))+abs(dc(i)));
        xyz0=[XYZ(tri(i,1),:).*(1-t)+XYZ(tri(i,3),:)*t];
        xyzp=[xyzp;xyz0];
    end

    % did we cross edge bc?
    if (db(i)*dc(i))<=0
        j=j+1;
        edgei=[edgei,j];
        t=abs(db(i))/(abs(db(i))+abs(dc(i)));
        xyz0=[XYZ(tri(i,2),:)*(1-t)+XYZ(tri(i,3),:)*t];
        xyzp=[xyzp;xyz0];
    end

    edgelist=[edgelist;edgei];
end

hold on
plot3(XYZ(:,1),XYZ(:,2),XYZ(:,3),'.')
plot3(p0(1),p0(2),p0(3),'ms')
plot3(xyzp(:,1),xyzp(:,2),xyzp(:,3),'r.')
hold off
return
========================================
function c=array_subs(a,b)

for i=1:length(a)
    c(i,:)=a(i,:)-b;
end
return

--------------------------------------------------------------------------------------
John D'Errico <derrico@flare.net> wrote in message <derrico-3DFA0B.09183408112001@news.newsguy.com>...
> This is fairly easy. We need not even assume that the
> object is convex.
>
> Assume your plane is represented as a point on the
> plane (P0) and a normal vector (P1) to the plane,
> and that P0 and P1 are (1x3) row vectors. I'll
> also assume that you have the set of points on
> which the triangulation is based in the (nx3)
> array XYZ. Finally, I'll assume the triangulation
> itself is an (mx3) integer array of indexes into
> the rows of XYZ. Call it TRI.
>
> % ============ begin matlab code ============
> % first, determine which triangles cross the plane.
> % vertex 1 of each triangle is:
> a = XYZ(tri(:,1),:);
> % likewise for vertex 2 and 3
> b = XYZ(tri(:,2),:);
> c = XYZ(tri(:,3),:);
>
> % on which side of the plane are each of a,b,c?
> % use a dot product (either the function dot or a
> % matrix multiply will do
> da=(a-repmat(p0,m,1)*p1';
> db=(b-repmat(p0,m,1)*p1';
> dc=(c-repmat(p0,m,1)*p1';
>
> % if exactly 1 or 2 of the corners are on the
> % "positive" side of the plane, then this face
> % crosses the plane. k will be a list of the
> % triangles the plane crosses
> k=(da>0)+(db>0)+(dc>0);
> k=find((k==1)|(k==2));
>
> % if k is not empty, then the plane had some
> % intersection with the object. I'll be lazy here
> % and loop over the faces crossed, although the
> % loop is easily vectorized
> edgelist=[];
> xyzp=[];
> j=0;
> for i=k
> edgei=[];
> % did we cross edge ab?
> if (da(i)*db(i))<=0
> j=j+1;
> edgei=j;
> t=abs(da(i))/(abs(da(i))+abs(db(i)));
> xyz0=XYZ(i,1)*(1-t)+XYZ(i,2)*t;
> xyzp=[xyzp;xyz0];
> end
> % did we cross edge ac?
> if (da(i)*dc(i))<=0
> j=j+1;
> edgei=[edgei,j];
> t=abs(da(i))/(abs(da(i))+abs(dc(i)));
> xyz0=XYZ(i,1)*(1-t)+XYZ(i,3)*t;
> xyzp=[xyzp;xyz0];
> end
> % did we cross edge bc?
> if (db(i)*dc(i))<=0
> j=j+1;
> edgei=[edgei,j];
> t=abs(db(i))/(abs(db(i))+abs(dc(i)));
> xyz0=XYZ(i,2)*(1-t)+XYZ(i,3)*t;
> xyzp=[xyzp;xyz0];
> end
>
> edgelist=[edgelist;edgei];
>
> end
> % ============ end matlab code ============
>
> Edgelist is a list of pairs of endpoints of
> line segments in the slice plane. It refers to
> rows of the array xyzp. These edges are in no
> special order.
>
> I appologize if there are bugs in this code. I
> have not tested it in matlab. You should be able
> to figure out what I am doing however and fix
> any bugs.
>
> HTH,
> John D'Errico
>
>
>
> In article <eea741b.-1@WebX.raydaftYaTP>, "Molly Dickens"
> <mdickens@coe.ttu.edu> wrote:
>
> > I have a triangulated object in 3D (i.e. a surface made up of
> > triangles). The handle to this object is a vector of handles to the
> > individual patch objects (triangles).
> >
> >
> > I want to be able to take a slice plane through this object. In
> > other words, for a given plane in the 3D space, I want to obtain the
> > polygon that is the intersection of that plane and my object.
> >
> >
> > The function 'slice' can be used to produce a slice plane when you
> > have volumetric data (3D matrix of values). But I don't have that
> > and don't know how to convert what I have to a volume (i.e. voxelize).
> >
> >
> > Any suggestions?!
> > Thanks,
> > Molly
>
> --
>

Tags for this Thread

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

rssFeed for this Thread

Contact us at files@mathworks.com