triplyPeriodicMinimal
Below is a demonstration of the features of the triplyPeriodicMinimal function
Contents
clear; close all; clc;
Syntax
S=triplyPeriodicMinimal(X,Y,Z,typeStr);
Description
This function creates the image S which can be used to define triply periodic minimal surfaces. The input consists of a grid of coordinates (X,Y,Z) and the surface type (typeStr).
Examples
clear; close all; clc;
Plot settings
cMap=jet(250); faceAlpha1=1; faceAlpha2=0.65; edgeColor1='none'; edgeColor2='none'; fontSize=25; pColors=gjet(6);
Example: Construct triply periodic minimal surfaces
%Create a grid n=35; [X,Y,Z]=meshgrid(linspace(-pi,pi,n)); %Evaluate triply periodic function S=triplyPeriodicMinimal(X,Y,Z,'p'); %Construct iso-surface [F,V] = isosurface(X,Y,Z,S,0);
Visualize surface
cFigure; hold on; title('Schwarz P-surface','FontSize',fontSize); gpatch(F,V,'kw','k',1); axisGeom; camlight headlight; drawnow;
Visualization all variations
cFigure; subplot(2,3,1); title('Schwarz P-surface','FontSize',fontSize); hold on; gpatch(F,V,pColors(1,:),'none',1); axisGeom; camlight headlight; lighting gouraud; view(-50,30); [X,Y,Z]=meshgrid(linspace(-pi,pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'d'); [F,V] = isosurface(X,Y,Z,S,0.1); subplot(2,3,2); title('d','FontSize',fontSize); hold on; gpatch(F,V,pColors(2,:),'none',1); axisGeom; camlight headlight; lighting gouraud; view(-50,30); [X,Y,Z]=meshgrid(linspace(-2*pi,2*pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'g'); [F,V] = isosurface(X,Y,Z,S,0.6); subplot(2,3,3); title('Gyroid','FontSize',fontSize); hold on; gpatch(F,V,pColors(3,:),'none',1); axisGeom; camlight headlight; lighting gouraud; view(-50,30); [X,Y,Z]=meshgrid(linspace(-pi,pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'n'); [F,V] = isosurface(X,Y,Z,S,0); subplot(2,3,4); title('Neovius','FontSize',fontSize); hold on; gpatch(F,V,pColors(4,:),'none',1); axisGeom; camlight headlight; lighting gouraud; view(-50,30); [X,Y,Z]=meshgrid(linspace(-pi,pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'w'); [F,V] = isosurface(X,Y,Z,S,0); subplot(2,3,5); title('w','FontSize',fontSize); hold on; gpatch(F,V,pColors(5,:),'none',1); axisGeom; camlight headlight; lighting gouraud; view(-50,30); [X,Y,Z]=meshgrid(linspace(-pi,pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'pw'); [F,V] = isosurface(X,Y,Z,S,0.5); subplot(2,3,6); title('pw','FontSize',fontSize); hold on; gpatch(F,V,pColors(6,:),'none',1); axisGeom; camlight headlight; lighting gouraud; view(-50,30); drawnow;
Example: Creating a hexahedral mesh of for a regular trabecular structure
This example renders boundary faces. Use the 'h' option for im2patch to obtain hexehadral elements.
n=50; [X,Y,Z]=meshgrid(linspace(-2*pi,2*pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'g'); T=0.6; c=(max(S(:))*T); L=S>=c; [F1,V1,C1]=im2patch(S,L,'vb'); L=S<c; [F2,V2,C2]=im2patch(S,L,'vb');
Visualization
cFigure; subplot(1,2,1); title('Gyroid based "network"','FontSize',fontSize); xlabel('J','FontSize',fontSize);ylabel('I','FontSize',fontSize); zlabel('K','FontSize',fontSize); hold on; gpatch(F1,V1,C1,'k',1); axisGeom; colormap(cMap); caxis([min(S(:)) max(S(:))]); camlight headlight; subplot(1,2,2); title('Gyroid based "matrix"','FontSize',fontSize); xlabel('J','FontSize',fontSize);ylabel('I','FontSize',fontSize); zlabel('K','FontSize',fontSize); hold on; gpatch(F2,V2,C2,'k',1); axisGeom; colormap(cMap); caxis([min(S(:)) max(S(:))]); camlight headlight; drawnow;
Example: Thickening the surfaces
n=75; typeStr='g'; switch typeStr case 'p' [X,Y,Z]=meshgrid(linspace(-pi,pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'p'); [F,V] = isosurface(X,Y,Z,S,0); case 'g' [X,Y,Z]=meshgrid(linspace(-1.9*pi,1.9*pi,n)); S=triplyPeriodicMinimal(X,Y,Z,'g'); [F,V] = isosurface(X,Y,Z,S,0); V=V./max(V(:)); %Normalize coordinates V=V*45/2; end F1=F; V1=V; %Store originals %Get boundary edges Eb=patchBoundary(F,V); % %Smoothen surface % controlPar.Method='HC'; % controlPar.n=5; % controlPar.RigidConstraints=unique(Eb(:)); % V=patchSmooth(F,V,[],controlPar);
Thicken surface in ward
thicknessOffset=1; %The desired thickness [~,~,N]=patchNormal(F,V); %Vertex normal vectors V1=V-N*thicknessOffset/2; %The offset coordinates V2=V+N*thicknessOffset/2; %The offset coordinates numVertices=size(V,1); V=[V1;V2]; %Append new coordinates F=[F;fliplr(F)+numVertices]; %Append new faces (note offset in indices) Ebb=[Eb;Eb+numVertices];
Close boundary features
optionStruct.outputType='label'; G=tesgroup(Eb,optionStruct); %grouping of boundary edges for q=1:1:max(G(:)) logicGroup=(G==q); Eb_now=Eb(logicGroup,:); fq=[Eb_now fliplr(Eb_now)+numVertices]; %New quadrilateral faces f=[fq(:,[1 2 3]); fq(:,[3 4 1]);]; %New triangular faces F=[F;fliplr(f)]; %Append new faces end [F,V,~,ind2]=mergeVertices(F,V); Ebb=ind2(Ebb); logic1=V(:,3)<(-45/2+0.1); V(logic1,3)=-45/2;
Visualize thickened surface
cFigure; hold on; hold on; title('Thickened surface','FontSize',fontSize); gpatch(F,V,'bw','none',1); gpatch(Ebb,V,'none','b',0,2); % patchNormPlot(F,V); %Visualize face normal directions axisGeom; camlight headlight; drawnow;
The model can be exported to an STL file using export_STL_txt, see HELP_export_STL_txt.
GIBBON www.gibboncode.org
Kevin Mattheus Moerman, [email protected]
GIBBON footer text
License: https://github.com/gibbonCode/GIBBON/blob/master/LICENSE
GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for image segmentation, image-based modeling, meshing, and finite element analysis.
Copyright (C) 2006-2021 Kevin Mattheus Moerman and the GIBBON contributors
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.