#pragma TextEncoding = "UTF-8" #pragma rtGlobals=3 // Use modern global access method and strict wave access #pragma DefaultTab={3,20,4} // Set default tab width in Igor Pro 9 and later //AI Note: Some of the code was written by Gemini Flash 3.5. function f_export_ply() //screen resolution string s_igor_info=IgorInfo(0) variable v_info_elements=itemsinList(s_igor_info,";") string s_screen_info=replaceString("RECT=",stringfromList(v_info_elements-1,s_igor_info,";"),"") variable v_screen1_width=abs(str2num(stringfromList(3,s_screen_info,","))-str2num(stringfromList(1,s_screen_info,","))) //relative position variable v_screen1_length=abs(str2num(stringfromList(4,s_screen_info,","))-str2num(stringfromList(2,s_screen_info,","))) variable v_sc1_width_mp=round(v_screen1_width/2) variable v_sc1_length_mp=round(v_screen1_length/2) if (stringmatch(IgorInfo(2),"Windows")==1) GetWindow kwFrameInner, wsize v_sc1_width_mp=round((V_right-V_left)/2) //relative position v_sc1_length_mp=round((V_bottom-V_top)/2) endif if (stringmatch(IgorInfo(2),"Macintosh")==1) GetMouse string s_Igorinfo = IgorInfo(0) string s_str variable v_n_screens=NumberByKey("NSCREENS", s_Igorinfo) //print v_n_screens variable v_i, v_screen_left, v_screen_top, v_screen_right, v_screen_bottom make/FREE/O/N=(v_n_screens,4) w_monitors for (v_i=1;v_i<=v_n_screens;v_i++) s_str = StringByKey("SCREEN"+num2str(v_i), s_Igorinfo) sscanf s_str, "DEPTH=%*d,RECT=%d,%d,%d,%d", v_screen_left, v_screen_top, v_screen_right, v_screen_bottom //print v_screen_left, v_screen_top, v_screen_right, v_screen_bottom w_monitors[v_i-1][0]=v_screen_left w_monitors[v_i-1][1]=v_screen_right w_monitors[v_i-1][2]=v_screen_top w_monitors[v_i-1][3]=v_screen_bottom endfor variable v_active_screen=1 for (v_i=1;v_i<=v_n_screens;v_i++) if ((v_left>=w_monitors[v_i-1][0])&&(v_left<=w_monitors[v_i-1][1])&&(v_top>=w_monitors[v_i-1][2])&&(v_top<=w_monitors[v_i-1][3])) v_active_screen=v_i endif endfor //print v_active_screen s_str = StringByKey("SCREEN"+num2str(v_active_screen), s_Igorinfo) sscanf s_str, "DEPTH=%*d,RECT=%d,%d,%d,%d", v_screen_left, v_screen_top, v_screen_right, v_screen_bottom //print v_screen_left, v_screen_right //print v_screen_top, v_screen_bottom v_sc1_width_mp=round((v_screen_right+v_screen_left)/2) //absolute position, negative values possible v_sc1_length_mp=round((v_screen_bottom+v_screen_top)/2) endif //variables for export variable v_1_min, v_1_max, v_1_active, v_2_min, v_2_max, v_2_active, v_3_min, v_3_max, v_3_active, v_4_min, v_4_max, v_4_active, v_5_min, v_5_max, v_5_active, v_6_min, v_6_max, v_6_active, v_7_min, v_7_max, v_7_active variable v_1_red, v_2_red, v_3_red, v_4_red, v_5_red, v_6_red, v_7_red, v_1_blue, v_2_blue, v_3_blue, v_4_blue, v_5_blue, v_6_blue, v_7_blue, v_1_green, v_2_green, v_3_green, v_4_green, v_5_green, v_6_green, v_7_green v_1_active = 1 v_2_active = 1 v_3_active = 1 v_4_active = 1 v_5_active = 1 v_6_active = 1 v_7_active = 1 //window for data input variable v_panel_left=v_sc1_width_mp-120 variable v_panel_rigth=v_sc1_width_mp+120 variable v_panel_top=v_sc1_length_mp-105 variable v_panel_bottom=v_sc1_length_mp+105 NewPanel/K=1/W=(v_panel_left,v_panel_top,v_panel_rigth,v_panel_bottom)/N=PLYExport as "Panel for export as PLY-File" // /W=(165,140,(425+165),(30*(quantity_waves)+110+140)) if (stringmatch(IgorInfo(2),"Macintosh")==1) MoveWindow v_panel_left,v_panel_top,-1,-1 //bug fix for negative positions on Macintosh endif ModifyPanel/W=PLYExport fixedSize=1 DrawText 70+10 ,25, "≥ Min." DrawText 130+5 ,25, "< Max." DrawText 190 ,25, "Active?" PopupMenu colorSelect_1, pos={10,35}, size={20,20}, title="" PopupMenu colorSelect_1, mode=1, value="*COLORPOP*" PopupMenu colorSelect_1, popColor=(65535, 0, 0) SetVariable v_1_min ,pos={70,35} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_1_max ,pos={130,35} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_1, pos={190+10,35+2.5},title="",value= 1, variable=v_1_active PopupMenu colorSelect_2, pos={10,55}, size={20,20}, title="" PopupMenu colorSelect_2, mode=1, value="*COLORPOP*" PopupMenu colorSelect_2, popColor=(65535, 42405, 0) SetVariable v_2_min ,pos={70,55} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_2_max ,pos={130,55} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_2, pos={190+10,55+2.5},title="",value= 1, variable=v_1_active PopupMenu colorSelect_3, pos={10,75}, size={20,20}, title="" PopupMenu colorSelect_3, mode=1, value="*COLORPOP*" PopupMenu colorSelect_3, popColor=(65535, 65535, 0) SetVariable v_3_min ,pos={70,75} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_3_max ,pos={130,75} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_3, pos={190+10,75+2.5},title="",value= 1, variable=v_1_active PopupMenu colorSelect_4, pos={10,95}, size={20,20}, title="" PopupMenu colorSelect_4, mode=1, value="*COLORPOP*" PopupMenu colorSelect_4, popColor=(0, 52428, 0) SetVariable v_4_min ,pos={70,95} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_4_max ,pos={130,95} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_4, pos={190+10,95+2.5},title="",value= 1, variable=v_1_active PopupMenu colorSelect_5, pos={10,115}, size={20,20}, title="" PopupMenu colorSelect_5, mode=1, value="*COLORPOP*" PopupMenu colorSelect_5, popColor=(0, 52428, 52428) SetVariable v_5_min ,pos={70,115} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_5_max ,pos={130,115} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_5, pos={190+10,115+2.5},title="",value= 1, variable=v_1_active PopupMenu colorSelect_6, pos={10,135}, size={20,20}, title="" PopupMenu colorSelect_6, mode=1, value="*COLORPOP*" PopupMenu colorSelect_6, popColor=(0, 0, 65535) SetVariable v_6_min ,pos={70,135} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_6_max ,pos={130,135} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_6, pos={190+10,135+2.5},title="",value= 1, variable=v_1_active PopupMenu colorSelect_7, pos={10,155}, size={20,20}, title="" PopupMenu colorSelect_7, mode=1, value="*COLORPOP*" PopupMenu colorSelect_7, popColor=(41120, 0, 57568) SetVariable v_7_min ,pos={70,155} ,value=_NUM:0, limits={-inf,inf,0} SetVariable v_7_max ,pos={130,155} ,value=_NUM:1, limits={-inf,inf,0} CheckBox c_v_7, pos={190+10,155+2.5},title="",value= 1, variable=v_1_active Button B_do_it,pos={190 ,185} ,size={40,20} ,title="Do it." ,proc=f_doit_ply end Function f_doit_ply(ctrlName) : ButtonControl String ctrlName f_do_ply() return 0 End Function f_do_ply() //check if data panel exists if (WinType("PLYExport") == 7) else Print "'PLYExport' panel is missing. Please use the function f_export_ply() to start an export." return -1 endif //transfer of data from panel Variable v_1_min, v_1_max, v_1_active, v_2_min, v_2_max, v_2_active, v_3_min, v_3_max, v_3_active, v_4_min, v_4_max, v_4_active, v_5_min, v_5_max, v_5_active, v_6_min, v_6_max, v_6_active, v_7_min, v_7_max, v_7_active Variable v_1_red, v_2_red, v_3_red, v_4_red, v_5_red, v_6_red, v_7_red, v_1_blue, v_2_blue, v_3_blue, v_4_blue, v_5_blue, v_6_blue, v_7_blue, v_1_green, v_2_green, v_3_green, v_4_green, v_5_green, v_6_green, v_7_green ControlInfo/W=PLYExport v_1_min; v_1_min=V_value ControlInfo/W=PLYExport v_1_max; v_1_max=V_value ControlInfo/W=PLYExport colorSelect_1; v_1_red=V_Red; v_1_green=V_Green; v_1_blue=V_Blue ControlInfo/W=PLYExport c_v_1; v_1_active=V_value ControlInfo/W=PLYExport v_2_min; v_2_min=V_value ControlInfo/W=PLYExport v_2_max; v_2_max=V_value ControlInfo/W=PLYExport colorSelect_2; v_2_red=V_Red; v_2_green=V_Green; v_2_blue=V_Blue ControlInfo/W=PLYExport c_v_2; v_2_active=V_value ControlInfo/W=PLYExport v_3_min; v_3_min=V_value ControlInfo/W=PLYExport v_3_max; v_3_max=V_value ControlInfo/W=PLYExport colorSelect_3; v_3_red=V_Red; v_3_green=V_Green; v_3_blue=V_Blue ControlInfo/W=PLYExport c_v_31; v_3_active=V_value ControlInfo/W=PLYExport v_4_min; v_4_min=V_value ControlInfo/W=PLYExport v_4_max; v_4_max=V_value ControlInfo/W=PLYExport colorSelect_4; v_4_red=V_Red; v_4_green=V_Green; v_4_blue=V_Blue ControlInfo/W=PLYExport c_v_4; v_4_active=V_value ControlInfo/W=PLYExport v_5_min; v_5_min=V_value ControlInfo/W=PLYExport v_5_max; v_5_max=V_value ControlInfo/W=PLYExport colorSelect_5; v_5_red=V_Red; v_5_green=V_Green; v_5_blue=V_Blue ControlInfo/W=PLYExport c_v_5; v_5_active=V_value ControlInfo/W=PLYExport v_6_min; v_6_min=V_value ControlInfo/W=PLYExport v_6_max; v_6_max=V_value ControlInfo/W=PLYExport colorSelect_6; v_6_red=V_Red; v_6_green=V_Green; v_6_blue=V_Blue ControlInfo/W=PLYExport c_v_6; v_6_active=V_value ControlInfo/W=PLYExport v_7_min; v_7_min=V_value ControlInfo/W=PLYExport v_7_max; v_7_max=V_value ControlInfo/W=PLYExport colorSelect_7; v_7_red=V_Red; v_7_green=V_Green; v_7_blue=V_Blue ControlInfo/W=PLYExport c_v_7; v_7_active=V_value //choose path Variable refNum String message = "Save PLY as..." String fileFilters = "PLY Files (*.ply):.ply;All Files:.*;" Open /D /F=fileFilters /M=message refNum as "unknown.ply" If (strlen(S_fileName) == 0) Print "Abort by user." Return 0 EndIf //choose waves String filePath = S_fileName String s_promptStr = "Choose 3-dim. waves for export:" CreateBrowser executeMode=2, prompt=s_promptStr, showWaves=1, showVars=0, showStrs=0 If (V_Flag == -1 || strlen(S_BrowserList) == 0) Print "Abort by user." Return 0 EndIf String selectionList = S_BrowserList Variable numSelected = ItemsInList(selectionList) Variable i, xIdx, yIdx, zIdx, fileID Variable redVal, greenVal, blueVal Variable val //count valid voxels Variable validVoxels = 0 for(i = 0; i < numSelected; i += 1) String waveName = StringFromList(i, selectionList) Wave w = $waveName Variable numX = DimSize(w, 0) Variable numY = DimSize(w, 1) Variable numZ = DimSize(w, 2) for(xIdx = 0; xIdx < numX; xIdx += 1) for(yIdx = 0; yIdx < numY; yIdx += 1) for(zIdx = 0; zIdx < numZ; zIdx += 1) val = w[xIdx][yIdx][zIdx] if ((v_1_active && val >= v_1_min && val < v_1_max) || \ (v_2_active && val >= v_2_min && val < v_2_max) || \ (v_3_active && val >= v_3_min && val < v_3_max) || \ (v_4_active && val >= v_4_min && val < v_4_max) || \ (v_5_active && val >= v_5_min && val < v_5_max) || \ (v_6_active && val >= v_6_min && val < v_6_max) || \ (v_7_active && val >= v_7_min && val < v_7_max)) validVoxels += 1 endif endfor endfor endfor endfor //cube: 8 vertices and 12 faces Variable totalVertices = validVoxels * 8 Variable totalFaces = validVoxels * 12 //PLY header Open fileID as filePath fprintf fileID, "ply\r\n" fprintf fileID, "format ascii 1.0\r\n" fprintf fileID, "element vertex %d\r\n", totalVertices fprintf fileID, "property float x\r\n" fprintf fileID, "property float y\r\n" fprintf fileID, "property float z\r\n" fprintf fileID, "property uchar red\r\n" fprintf fileID, "property uchar green\r\n" fprintf fileID, "property uchar blue\r\n" fprintf fileID, "element face %d\r\n", totalFaces fprintf fileID, "property list uchar int vertex_indices\r\n" fprintf fileID, "end_header\r\n" //generate vertices Variable x0, x1, y0, y1, z0, z1 for(i = 0; i < numSelected; i += 1) Wave dataWave = $StringFromList(i, selectionList) Variable nX = DimSize(dataWave, 0), nY = DimSize(dataWave, 1), nZ = DimSize(dataWave, 2) Variable xOff = DimOffset(dataWave, 0), xDel = DimDelta(dataWave, 0) Variable yOff = DimOffset(dataWave, 1), yDel = DimDelta(dataWave, 1) Variable zOff = DimOffset(dataWave, 2), zDel = DimDelta(dataWave, 2) for(xIdx = 0; xIdx < nX; xIdx += 1) x0 = xOff + xIdx * xDel; x1 = x0 + xDel for(yIdx = 0; yIdx < nY; yIdx += 1) y0 = yOff + yIdx * yDel; y1 = y0 + yDel for(zIdx = 0; zIdx < nZ; zIdx += 1) z0 = zOff + zIdx * zDel; z1 = z0 + zDel val = dataWave[xIdx][yIdx][zIdx] Variable hasMatch = 0 if (v_1_active && val >= v_1_min && val < v_1_max) redVal = v_1_red; greenVal = v_1_green; blueVal = v_1_blue; hasMatch = 1 elseif (v_2_active && val >= v_2_min && val < v_2_max) redVal = v_2_red; greenVal = v_2_green; blueVal = v_2_blue; hasMatch = 1 elseif (v_3_active && val >= v_3_min && val < v_3_max) redVal = v_3_red; greenVal = v_3_green; blueVal = v_3_blue; hasMatch = 1 elseif (v_4_active && val >= v_4_min && val < v_4_max) redVal = v_4_red; greenVal = v_4_green; blueVal = v_4_blue; hasMatch = 1 elseif (v_5_active && val >= v_5_min && val < v_5_max) redVal = v_5_red; greenVal = v_5_green; blueVal = v_5_blue; hasMatch = 1 elseif (v_6_active && val >= v_6_min && val < v_6_max) redVal = v_6_red; greenVal = v_6_green; blueVal = v_6_blue; hasMatch = 1 elseif (v_7_active && val >= v_7_min && val < v_7_max) redVal = v_7_red; greenVal = v_7_green; blueVal = v_7_blue; hasMatch = 1 endif if (hasMatch == 0) continue endif //write 8 vertices, order is important for calculating area fprintf fileID, "%f %f %f %d %d %d\r\n", x0, y0, z0, redVal, greenVal, blueVal // 0 fprintf fileID, "%f %f %f %d %d %d\r\n", x1, y0, z0, redVal, greenVal, blueVal // 1 fprintf fileID, "%f %f %f %d %d %d\r\n", x1, y1, z0, redVal, greenVal, blueVal // 2 fprintf fileID, "%f %f %f %d %d %d\r\n", x0, y1, z0, redVal, greenVal, blueVal // 3 fprintf fileID, "%f %f %f %d %d %d\r\n", x0, y0, z1, redVal, greenVal, blueVal // 4 fprintf fileID, "%f %f %f %d %d %d\r\n", x1, y0, z1, redVal, greenVal, blueVal // 5 fprintf fileID, "%f %f %f %d %d %d\r\n", x1, y1, z1, redVal, greenVal, blueVal // 6 fprintf fileID, "%f %f %f %d %d %d\r\n", x0, y1, z1, redVal, greenVal, blueVal // 7 endfor endfor endfor endfor //link faces Variable vOffset = 0 for(i = 0; i < numSelected; i += 1) Wave dataWave = $StringFromList(i, selectionList) nX = DimSize(dataWave, 0) nY = DimSize(dataWave, 1) nZ = DimSize(dataWave, 2) for(xIdx = 0; xIdx < nX; xIdx += 1) for(yIdx = 0; yIdx < nY; yIdx += 1) for(zIdx = 0; zIdx < nZ; zIdx += 1) val = dataWave[xIdx][yIdx][zIdx] if ((v_1_active && val >= v_1_min && val < v_1_max) || \ (v_2_active && val >= v_2_min && val < v_2_max) || \ (v_3_active && val >= v_3_min && val < v_3_max) || \ (v_4_active && val >= v_4_min && val < v_4_max) || \ (v_5_active && val >= v_5_min && val < v_5_max) || \ (v_6_active && val >= v_6_min && val < v_6_max) || \ (v_7_active && val >= v_7_min && val < v_7_max)) //(2 triangles for each side) //top fprintf fileID, "3 %d %d %d\r\n", vOffset+0, vOffset+3, vOffset+2 fprintf fileID, "3 %d %d %d\r\n", vOffset+0, vOffset+2, vOffset+1 //bottom fprintf fileID, "3 %d %d %d\r\n", vOffset+4, vOffset+5, vOffset+6 fprintf fileID, "3 %d %d %d\r\n", vOffset+4, vOffset+6, vOffset+7 //front fprintf fileID, "3 %d %d %d\r\n", vOffset+0, vOffset+1, vOffset+5 fprintf fileID, "3 %d %d %d\r\n", vOffset+0, vOffset+5, vOffset+4 //back fprintf fileID, "3 %d %d %d\r\n", vOffset+2, vOffset+3, vOffset+7 fprintf fileID, "3 %d %d %d\r\n", vOffset+2, vOffset+7, vOffset+6 //left fprintf fileID, "3 %d %d %d\r\n", vOffset+0, vOffset+4, vOffset+7 fprintf fileID, "3 %d %d %d\r\n", vOffset+0, vOffset+7, vOffset+3 //right fprintf fileID, "3 %d %d %d\r\n", vOffset+1, vOffset+2, vOffset+6 fprintf fileID, "3 %d %d %d\r\n", vOffset+1, vOffset+6, vOffset+5 //each cube has 8 vertices, index+=8 for next cube vOffset += 8 endif endfor endfor endfor endfor Close fileID Print "PLY Export completed successfully." Return 1 End