Tutorial: Generation of 3D objects from 2D contours through extrusion and rotation
Prof. Dr. Tim C. Lueth, Professor at Technical University of Munich, MIMED - Department of Mechanical Engineering, Munich, August 2025
clear, close all % Important for script development. The line can be removed later.
==== PART 1 ============================================================
An example contour that we want to extrude
When two contours, CPLA and CPLB, are connected to form a body, then in the simplest case there are
- A lower surface (floor) consists of the tessellation/triangulation of CPLA (surface orientation facing downwards).
- An upper surface (cover) consists of the tessellation/triangulation of CPLA (surface orientation facing upwards).
- One wall (outward for the right-hand rule, inward for the left-hand rule)
Converting the embedded CPL into a point list and an edge list with "PLELofCPL"
Wir zerlegen CPLA in PLA und ELA
[PL,EL]=PLELofCPL(CPL)
0 -5
10 -10
5 0
10 5
5 10
0 5
0 10
-5 5
-10 10
-5 0
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
SGfigure(0,90); VLELplots(PL,EL,'r.-',.5,.5,.5);
For the ground floor and ceiling cover, we tessellate PLA and ELA into triangles using "delaunayTriangulation."
TR=delaunayTriangulation(PL,EL);
VLFLplot(TR.Points,TR.ConnectivityList,'r',0.1);
However, we are only looking for triangles that are enclosed by the edge list with "isInterior".
We select the facets enclosed by the edges of the contour. "isInterior" selects only the facets that are inside of edges that define a triangle facet by tight hand rule
VLA=TR.Points; FLA=TR.ConnectivityList(iia,:);
We still need to flip the normal vector of the surfaces, as the ground floor of the body must point downwards.
FLA=FLA(:,[1 3 2]); % Change in the direction of the nromal vector of the surface from top to bottom
VLFLplotalpha(VLA,FLA,'m',1,'k');
VLFLplot(VLA,FLA,'m',2,5); view(-30,30)
We can now represent the bottom of the body as a surface.
SGfigure(-30,30); VLFLplot(VLA,FLA,'g');
Ceiling cover with the same contour but normal vector pointing upwards
VLB=VLaddz(VLA(:,1:2),30); FLB=TR.ConnectivityList(iia,:);
We can now represent the bottom of the body and the lid as surfaces.
SGfigure(-30,30); VLFLplot(VLB,FLB,'r','',5); VLFLplot(VLA,FLA,'g','',5);
We can automatically determine the wall surfaces of a contour from the edge lists.
VL=[VLA;VLaddz(VLA(:,1:2),30)];
FL1=[EL(:,1) EL(:,2) EL(:,2)+nva]; % FLcontourwallELn
FL2=[EL(:,1) EL(:,2)+nva EL(:,1)+nva]; % FLcontourwallELn
VLFLplot(VL,FLWA,'y','',5);
However, this can only be achieved so easily (with two lines) if the two contours at the top and bottom are similar
- have the same number of points
- have the same orientation/direction of rotation (clockwise/counterclockwise)
- have matching starting points when forming the surface
- have the same bend directions
- have the same distances between the bends
- have the same points on the straight lines between the bends
For embedded contours, the two contours must also
- consist of the same number of outer contours
- the respective outer contours of A can be assigned to corresponding outer contours of B
- this can also be applied to all inner contours and their inner outer contours
- missing inner contours can be closed or missing inner outer contours can be started
[VL,FL,FLW,FLU,FLO]=VLFLofPLELz(VLA(:,1:2),EL,30);
VLFLplotalpha(VL,FLW,'y',0.9);
VLFLplotalpha(VL,FLU,'g',1);
VLFLplotalpha(VL,FLO,'r',0.9);
==== PART 2 ============================================================
"SGofCPLz" Erzeugen von Körper durch Extrusion in der Höhe z
SGofCPLz(CPLsample(38),15);
SGofCPLz(CPLsample(38),[-10 10]);
SGofCPLz([PLcircle(15);nan nan;PLcircle(16)],15)
ans =
VL: [224×3 double]
FL: [448×3 double]
SGofCPLz([PLcircle(15);nan nan;PLcircle(16)],15,'floor',5); VLFLplotlight(1,0.5);
SGofCPLz([PLcircle(15);nan nan;PLcircle(16)],15,'cover',5); VLFLplotlight(1,0.5);
SGofCPLz(PLsquare(30,20),10);
SGofCPLz(PLsquare(30,20),10,'wall',2,'floor',2);
SGofCPLz(PLsquare(30,20),10,'wall',2,'floor',2,'cover',2); VLFLplotlight(1,0.5);
SGofCPLz(PLsquare(30,20),10,'wall',2,'floor',2,'flsub',PLcircle(7)); VLFLplotlight(1,0.5);
SGofCPLz(PLsquare(30,20),10,'wall',2,'cover',2,'csub',PLcircle(7)); % csub works only without walls
SGofCPLz([PLcircle(15);nan nan;PLcircle(16)],15,'cover',5,'csub',PLsquare(10)); % csub works only without walls
"SGofCPLextrude"
SGofCPLextrude(CPLsample(7),50','y');
SGofCPLextrude(CPLsample(7),50','x');
"SGofCPLflat"
SGofCPLflat(CPLsample(7));
"SGofCPLrot"
SGofCPLrot(PLtransP(CPLsample(7),[30 0]));
"SGofCPLrota"
SGofCPLrota(PLtransP(CPLsample(7),[30 0]),pi);
"SGofCPLzchamfer"
SGofCPLzchamfer(CPLsample(8),10,1);
"SGofCPLzdelaunayGrid" if on edges and in plane x and y should be auxiliary grid points
SGofCPLzdelaunayGrid(CPLsample(8),10,1,1,1);
PLFLofCPLdelaunayGrid: (line 65)
9.8079 1.9509
9.4346 2.8521
9.0613 3.7533
8.6880 4.6545
8.3147 5.5557
7.6249 6.2455
6.9352 6.9352
6.2455 7.6249
5.5557 8.3147
4.6545 8.6880
"SGaddsurfpoints" if also in z there should be auxiliary grid points
SGaddsurfpoints(SGofCPLz(CPLsample(8),10),'',[1,1,1]);
SGmakedoublevertex
ans =
VL: [2632×3 double]
FL: [5250×3 double]
FC: [5245×3 double]
"SGofCPLztwist"
SGofCPLztwist(PLrope([4 1],[1 .5],false),5);
"SGofCPLextrudealongCPL"
SGofCPLextrudealongCPL(PLsquare(3),PLsquare(40)); % Edge Problems - Outdated better use "SGofCPLcontourinstead"
"SGofCPLcontour"
SGofCPLcontour(PLsquare(3),PLsquare(40));
SGofCPLcontour(PLsquare(3),PLsquare(40),false);
"SGofCPLTL" (uses "SGof2CPLzheurist")
CPLC=[CPLC;nan nan;CPLbuffer(CPLC,-5)];
PL=[0 0; 0 80; 80 80; 80 40; 160 0];
PL=VLaddz(PL); PL(end,3)=80;
Ro=rofcirclearoundCPL(CPLC);
TL=TLofCVL(PL,Ro*1.1,'','','rad',false);
SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG,'y'); tplot(TL(:,:,1),30); tplot(TL(:,:,end),30);
The main function to create the path is "TLofCVL" that supports torsion or no torsion and rad, rmax, tan torsion is required, if start and end frame force a rotation of the solid in the direction of the path It is also possible to enforce an start frame in addition to the path
TL=TLofCVL(PL,Ro*1.1,eye(4),'','rad',true); % With Torsion
TLadjustR: NEED TO ROTATE STARTFRAME BY 1 degree
TLadjustR: NEED TO ROTATE ENDFRAME BY 159 degree
SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG,'y'); tplot(TL(:,:,1),30); tplot(TL(:,:,end),30);
It is also possible to enforce an end frame in addition to the path
TL=TLofCVL(PL,Ro*1.1,eye(4),TofPez([160 0 80],[0 0 1]),'rad',true); % With Torsion
TLadjustR: NEED TO ROTATE STARTFRAME BY 1 degree
TLadjustR: NEED TO ROTATE ENDFRAME BY 147 degree
SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG,'y'); tplot(TL(:,:,1),30); tplot(TL(:,:,end),30);
It is also possible to use the maximum radius (required for VLtangentcirc)
TL=TLofCVL(PL,Ro*2,eye(4),TofPez([160 0 80],[0 0 1]),'rma',true); % With Torsion
TLadjustR: NEED TO ROTATE STARTFRAME BY 1 degree
TLadjustR: NEED TO ROTATE ENDFRAME BY 151 degree
% SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG);
SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG,'y'); tplot(TL(:,:,1),30); tplot(TL(:,:,end),30);
It is also possible to enforce tangential loop if the radius is to big (required for VLtangentcirc)
TL=TLofCVL(PL,Ro*2,eye(4),TofPez([160 0 80],[0 0 1]),'tan',true); % With Torsion
TLadjustR: NEED TO ROTATE STARTFRAME BY -1 degree
TLadjustR: NEED TO ROTATE ENDFRAME BY 148 degree
% SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG);
SG=SGofCPLTL(CPLC,TL); SGfigure(-30,30); SGplotalpha(SG,'y'); tplot(TL(:,:,1),30); tplot(TL(:,:,end),30);
"SGofCPLtransT" für embedded CPL and multiple cross sections
SGofCPLtransT(CPLsample(13),eye(4),TofR(rot(0,0,pi/20),[0 0 40]));
TL=TLofCVL(VLsample(4)/2,2,eye(3),rot(0,0,pi/2),'rad');
TLadjustR: NEED TO ROTATE ENDFRAME BY 90 degree
SG=SGofCPLtransT(CPLsample(27)/20,TL); SGfigure(SG); view(-30,30); zoompatch('',0.01); camlightTL;
"SGofCPLCVLR" uses "VLinsertEulerSteps" and "SGcontourtube" => Should be replaced by SGofCPLtransT combined with TLofCVL
VL=[0 0 0; 0 0 10; 0 0 20; 10 0 20; 15 0 20; 20 0 20;20 20 20];
CPL=[PLcircle(5);NaN NaN;PLcircle(3,4)];
SGofCPLCVLR(CPL/2,VL,r); % Solution with Radial Edges
Positive Radius leads to radial edges
SGofCPLCVLR(CPL/2,VL,r); % Solution with Radial Edges
Negative Radius leads to Bezier contours
SGofCPLCVLR(CPL/2,VL,-r); % Solution with Bezier
Warning: 1st Euler angle does not fit to vertex list path direction
Warning: Last Euler angle does not fit to vertex list path direction
"SGofCPLtransT" but without Bezier and
TL=TLofCVL(VL,r,eye(4));
TLadjustR: NEED TO ROTATE STARTFRAME BY -45 degree
TLadjustR: NEED TO ROTATE ENDFRAME BY -90 degree
"SGofCPLreinforcement"
CPLi=CPLsample(36)*5; SGofCPLz([CPLbuffer(CPLi,1);nan nan;CPLi],5); SG=ans;
SGofCPLreinforcement(CPLbuffer(CPLi,1),[-2 2 0]); SGplotalpha(SG,'g',0.5) % Outer contour
Warning: Duplicate edge constraints have been detected and removed.
Warning: Duplicate edge constraints have been detected and removed.
ans =
Patch with properties:
FaceColor: 'flat'
FaceAlpha: 0.5000
EdgeColor: 'none'
LineStyle: '-'
Faces: [280×3 double]
Vertices: [140×3 double]
Show all properties
"SGofCPLbendonadrum" bends an extruded thin CPL on a drum (Stents)
CPL=[PLsquare(80);nan nan;PLsquare(100)]; SGofCPLbendonadrum(CPL,2)
PLFLofCPLdelaunayGrid: (line 65)
-40.0000 40.0000
-39.1489 40.0000
-38.2979 40.0000
-37.4468 40.0000
-36.5957 40.0000
-35.7447 40.0000
-34.8936 40.0000
-34.0426 40.0000
-33.1915 40.0000
-32.3404 40.0000
ans =
VL: [11016×3 double]
FL: [22032×3 double]
==== PART 3 ============================================================
Finally, let's look at how to connect two different contours with the same configuration.
"SGof2CPLzheurist"
SGof2CPLzheurist(CPLsample(7),CPLsample(8),10); VLFLplotlight(0,1);
SGof2CPLzheurist(PLaddauxpoints(CPLsample(7),1),CPLsample(8),10); VLFLplotlight(0,1);
SGof2CPLzheurist(PLaddauxpoints(CPLsample(7),1),PLaddauxpoints(CPLsample(8),1),10); VLFLplotlight(0,1);
Warning: Duplicate edge constraints have been detected and removed.
Everything else on the topic of "connecting different contours to a solid" will follow in another tutorial.
stamp
stamp: Mac OSX 15.6 | R2024b Update 6 | SG-Lib 5.4 | Java 1.8.0_202-b08 | i7-Intelx64 6-Core 64GByte RAM | 14-Aug-2025 06:23:30