This blog describes how to make 3D boxes like the following picture by a LabTalk function. (Click picture to enlarge.)
This graph sample was created by the following LabTalk code, which contains four functions – plot3DBox to make a single 3D box and its subroutines plotOneSide and cleanMatData, and the main function make3DBoxes to create multiple boxes specified in a worksheet (Book1 in above sample). You can run the program by simply issuing make3DBoxes command in the Script window,
[Main] @global = 1; //Set the following as global functions // The explanation of this script can be find in the blog at: https://blog.originlab.com/graphing/how-to-plot-3d-cubes-in-origin //################################################################################################ function int plotOneSide(int isheet, string gname$, int colorN) { if(exist(gname$)!=3) //Plot the face in new graph plotm im:=[%K]$(isheet)!1 plot:=103 x:=2 y:=3; else //Plot the face into existing graph plotm im:=[%K]$(isheet)!1 plot:=103 x:=2 y:=3 ogl:=[gname$]1!; set %K@$(isheet) -b3cc colorN; //Set color set %K@$(isheet) -b3m 0; //No meshgrid return 0; } //################################################################################################ function int cleanMatData(string mname$, int isheet) { //Copy face matrix to a Msheet range minp=[%(mname$)]1!1, mout=[%K]$(isheet)!1; mcopy im:=minp om:=mout; range minp=[%(mname$)]1!2, mout=[%K]$(isheet)!2; mcopy im:=minp om:=mout; range minp=[%(mname$)]1!3, mout=[%K]$(isheet)!3; mcopy im:=minp om:=mout; layer.name$=mname$; //Give the face name to the MSheet window -cd %(mname$); //Delete original matrix Return 0; } //################################################################################################ function int plot3DBox(ref string gname$, double Px1, double Py1, double Pz1, double Wx, double Wy, double Wz, int colorLR, int colorFB, int colorTB) { double Px2=Px1+Wx, Py2=Py1+Wy, Pz2=Pz1+Wz; int newg = exist(gname$)==3?0:1; //Flag whether new graph, or not int npts = 2; //Face matrix dimension window -t mat; //Make a new MBook %K=%H; //MBook name page.comments$="Pos=["+Text(Px1)$+","+Text(Py1)$+","+Text(Pz1)$+"] Dim=["+Text(Wx)$+","+Text(Wy)$+","+Text(Wz)$+"]"; ///////////////// Create Matrices for 3D pParametric Function Plot /////////////////////////// //// LEFT /////////////////////////////////////////////////// create myx -fp2 npts u Px1 Px2 npts Pz1 Pz2; //Create 2D loose datasets for X create myy -fp2 npts Py1 Px1 Px2 npts Pz1 Pz2; //Create 2D loose datasets for Y create myz -fp2 npts v Px1 Px2 npts Pz1 Pz2; //Create 2D loose datasets for Z create LEFT -mfph myz myx myy "u,v"; //Create matrices for LEFT for 3D parametric function plot cleanMatData("LEFT",2); //// RIGHT /////////////////////////////////////////////////// create myx -fp2 npts u Px2 Px1 npts Pz1 Pz2; //Create 2D loose datasets for X: Outward face create myy -fp2 npts Py2 Px1 Px2 npts Pz1 Pz2; //Create 2D loose datasets for Y create myz -fp2 npts v Px1 Px2 npts Pz1 Pz2; //Create 2D loose datasets for Z create RIGHT -mfph myz myx myy "u,v"; //Create matrices for RIGHT cleanMatData("RIGHT",3); //// FRONT /////////////////////////////////////////////////// create myx -fp2 npts Px2 Py1 Py2 npts Pz1 Pz2; //Create 2D loose datasets for X create myy -fp2 npts u Py1 Py2 npts Pz1 Pz2; //Create 2D loose datasets for Y create myz -fp2 npts v Py1 Py2 npts Pz1 Pz2; //Create 2D loose datasets for Z create FRONT -mfph myz myx myy "u,v"; //Create matrices for FRONT cleanMatData("FRONT",4); //// BACK /////////////////////////////////////////////////// create myx -fp2 npts Px1 Py1 Py2 npts Pz1 Pz2; //Create 2D loose datasets for X create myy -fp2 npts u Py2 Py1 npts Pz2 Pz1; //Create 2D loose datasets for Y: Outward face create myz -fp2 npts v Py1 Py2 npts Pz1 Pz2; //Create 2D loose datasets for Z create BACK -mfph myz myx myy "u,v"; //Create matrices for BACK cleanMatData("BACK",5); //// TOP /////////////////////////////////////////////////// create myx -fp2 npts u Px1 Px2 npts Py1 Py2; //Create 2D loose datasets for X create myy -fp2 npts v Px1 Px2 npts Py1 Py2; //Create 2D loose datasets for Y create myz -fp2 npts Pz2 Px1 Px2 npts Py1 Py2; //Create 2D loose datasets for Z create TOP -mfph myz myx myy "u,v"; //Create matrices for TOP cleanMatData("TOP",6); //// BOTTOM /////////////////////////////////////////////////// create myx -fp2 npts u Px2 Px1 npts Py1 Py2; //Create 2D loose datasets for X: Outward face create myy -fp2 npts v Px1 Px2 npts Py1 Py2; //Create 2D loose datasets for Y create myz -fp2 npts Pz1 Px1 Px2 npts Py1 Py2; //Create 2D loose datasets for Z create BOTTOM -mfph myz myx myy "u,v"; //Create matrices for BOTTOM cleanMatData("BOTTOM",7); ////////////////////////////////////////////////////////// //Make All Faces of the 3D Box if(newg==0) { //Add a plot to the existing gname$ for LEFT win -o %(gname$) { plotOneSide(2, gname$, colorLR); //plot LEFT wall in CYAN } } else { //Create a new graph for LEFT plotOneSide(2, gname$, colorLR); //plot LEFT wall in CYAN gname$=%H; //hold the created graph window name } win -o %(gname$) { //Make other faces plotOneSide(3, gname$, colorLR); //plot RIGHT wall in CYAN plotOneSide(4, gname$, colorFB); //plot FRONT wall in CYAN plotOneSide(5, gname$, colorFB); //plot BACK wall in CYAN plotOneSide(6, gname$, colorTB); //plot TOP wall in CYAN plotOneSide(7, gname$, colorTB); //plot BOTTOM wall in CYAN } window -a %K; //Activate the MBook layer -d 1; //Delete unnecessary first MSheet window -hc 1 %K; //Hide matrix window return 0; } //################################################################################################ function int make3DBoxes() { //Make 3D Boxes from a Worksheet if(exist(%H)!=2) { type -a [make3DBoxes] Error! The current window is not a workbook.; Return 0; } if(wks.nCols<9) { type -a [make3DBoxes] Error! Your worksheet does not have necessary 9 columns.; Return 0; } int nr=wks.maxRows; range rPx=col(1); //X column of Base Point range rPy=col(2); //Y column of Base Point range rPz=col(3); //Z column of Base Point range rWx=col(4); //Column of X length range rWy=col(5); //Column of Y length range rWz=col(6); //Column of Z length range rcLR=col(7); //Column for LEFT/RIGHT color range rcFB=col(8); //Column for FRONT/BACK color range rcTB=col(9); //Column for TOP/BOTTOM color string str$; for(ii=1; ii<=nr; ii++) { plot3DBox(str, rPx[ii],rPy[ii],rPz[ii], rWx[ii],rWy[ii],rWz[ii], rcLR[ii],rcFB[ii],rcTB[ii]); } type -a [make3DBoxes] Total $(nr) 3D boxes have been created.; Return 0; } //################################################################################################ @global = 0; //End of the global functions
Procedure
To Run this Script to make 3D Boxes from a worksheet data, you can follow the four steps below:
1) Using Notepad, save this script code as a script file, make3DBoxes.OGS in your User Files Folder(UFF).
Or, you can download the ZIP file of the code from here , and put the content “make3DBoxes.OGS” in the ZIP file into your UFF.
(To open your UFF location, choose “Help: Open Folder: User Files Folder” menu in Origin.)
2) For startup loading of the global functions, find Origin.INI file in your UFF, open it by Notepad, find “[Startup]” section, insert the following line just under this section line (where # is a number like 1, 2, 3,…):
File#=3DBoxes.OGS
and save it. Now you are ready to run “make3DBoxes” command any time available in Origin as described in the following steps. (See the details of these two steps here.)
3) Start Origin (your global functions will be automatically loaded), create a worksheet with 9 columns, and enter the data of your boxes. Each row of the worksheet specifies a box’s corner position, dimensions, and the colors. (See the sample worksheet in the above screenshot.) The columns contain the following data:
Column 1/2/3 : the base coordinates, X/Y/Z coordinates
Column 4/5/6 : Dimensions of the 3D box in X/Y/Z directions
Column 7/8/9 : Face pair colors of Right+Left/Front+Back/Top+Bottom. (1=Black, 2=Red, 3=Green, 4=Blue,… etc. See the whole color list.)
4) Set the worksheet active, and issue the following command in the Command window or in Script window:
make3DBoxes
Origin now draws 3D boxes specified in the worksheet, in a graph window.
If you want to draw a 3D box in an existing 3D graph such as with a 3D scatter plot, you can issue a command like the following:
string str$=%H; //Set the current graph name plot3DBox(str, 0, 0, 0, 1, 1, 1, 8, 3, 11); //Make a 3D box into the graph where P=[0,0,0], Dim=[1,1,1], Colors=[8,3,9]
Finally, note that you can customize this sample code for your needs such as for specifying subtle colors using RGB values (using color() function), specifying six distinct colors for all faces (by increasing the number of color arguments), drawing edge lines (by overlaying 3D line plots), etc.
Notes
1: Currently LabTalk lacks the capability to control the transparency of the surface. OriginLab is working to implement this feature, and once it is done, I will update the above sample code.
2: This script code was modified from the sample code in this help page. In this sample code, you can find a sample function to draw a sphere.
3: You can also make a function to create a rectangle (similar to plotOneSide in this blog’s sample) by creating two triangles as a “triangle patch” from a worksheet which contains 4 columns; the first three for corner XYZ coordinates, and the fourth for the route of the corner connections. After creating the worksheet, you can create a Color Fill 3D Surface plot, then execute “Set -spi ” command like the following pseudo code:
plotxyz iz:=<<Zcolumn>> plot:=103 ogl:=<new template:=glMESH.otp>; //Plot Color Fill Surface set <<Zcolumn>> -spi 2; //Set the next right column of Z to the route of the "triangular-patch"