Showing posts with label range3. Show all posts
Showing posts with label range3. Show all posts

Thursday, March 28, 2019

利用 Msys2 編譯 Multiphysics 分析套件 Range3

編譯步驟

https://github.com/Range-Software/range3 是一套能夠進行機構應力與熱流力分析的電腦輔助工程分析套件.

利用 Msys2 執行 Range3 編譯的流程與 https://2019wcm.blogspot.com/2019/03/v-rep.html 類似, 只需透過

pacman -Sy mingw-w64-x86_64-ffmpeg

加裝 ffmpeg 模組, 然後進入 Range3 目錄中的 range 目錄, 執行

qmake -o Makefile range.pro

mingw32-make -f Makefile

就可以在 Range3/range/Range 目錄中得到 Range_debug.exe, 執行時除了可攜系統中必要的 dll 檔案外, 必須額外下載 libcrypto-1_1-x64.dll 檔案, 就可以開啟執行.

自行利用 Msys2 編譯的 Range3, 由於完全獨立於 Windows 系統中的各動態程式庫, 因此相對於採用 Visual Studio 所的到的 100 MB 套件容量, 上述流程編譯取得的 Range3 容量將高達 1 GB 左右.

參考資料

kmol_range3.7z 下載

電子教科書:

Finite Elements - A Gentle Introduction
https://link.springer.com/book/10.1007/978-1-349-13898-2

Finite Element Methods - A Practical Guide
https://link.springer.com/book/10.1007/978-3-319-49971-0

An Introduction to Linear and Nonlinear Finite Element Analysis - A Computational Approach
https://link.springer.com/book/10.1007/978-0-8176-8160-9

Finite Elements Methods in Mechanics
https://link.springer.com/book/10.1007/978-3-319-08037-6

One-Dimensional Finite Elements - An Introduction to the FE Method
https://link.springer.com/book/10.1007/978-3-319-75145-0

Development and Application of the Finite Element Method based on Matlab
https://link.springer.com/book/10.1007/978-3-642-13153-0

Finite Element Methods for Engineering Sciences - Theoretical Approach and Problem Solving Techniques
https://link.springer.com/book/10.1007/978-3-540-76343-7

Range CAE 開發歷史:

2006.08.19 - 推出 0.9.5-2 版 (GUI 採 GTK+ 編寫)
2006.9.28 - 推出 0.9.6-1 版 (GUI 採 GTK+ 編寫)
2006.10.1 - 推出 0.9.6-2 版 (GUI 採 GTK+ 編寫)
2006.10.27 - 推出 1.0.0-RC1 版 (GUI 採 GTK+ 編寫)
2007.09.17 - 推出 1.1 版 (GUI 採 GTK+ 編寫)
2007.12.18 - 推出 1.2 版 (GUI 採 GTK+ 編寫)
2008.02.25 - 推出 1.3 版 (GUI 採 GTK+ 編寫)
2008.04.07 - 推出 1.4 版 (GUI 採 GTK+ 編寫)
2008.06.23 - 推出 1.5 版 (GUI 採 GTK+ 編寫)
2008.10.30 - 推出 1.6 版 (GUI 採 GTK+ 編寫)
2009.02.16 - 推出 1.9 版 (GUI 採 GTK+ 編寫)
2010.01.18 - 推出 2.1 版 (GUI 採 GTK+ 編寫)
2010.06.01 - 推出 2.2 版 (GUI 採 GTK+ 編寫)
2011.09.05 - 推出 2.3 版 (GUI 採 GTK+ 編寫)

Range CAE 以 Qt 改寫

2018.04.30 - 推出 3.0 版, 原始碼以 GPL3 授權釋出 (GUI 採 Qt 編寫)
2018.11.08 - 推出 3.1 版 (GUI 採 Qt 編寫)
2019.01.12 - 推出 3.2 版 (GUI 採 Qt 編寫)

其他原始碼:

https://github.com/FreeFem/FreeFem-sources

https://github.com/FreeFem/FreeFem-doc

https://github.com/ritchie46/anaStruct

https://github.com/ruimaciel/femp

https://github.com/AppliedMechanics-EAFIT/SolidsPy

Sunday, March 3, 2019

在 MSYS2 環境編譯 Solvespace

 以下引用一篇位於 http://project.mde.tw/blog/zai-msys2-huan-jing-bian-yi-solvespace.html 的舊文章.

能夠自行利用隨身碟上的 MSYS2 在 Windows 10 64 位元環境中編譯 https://github.com/solvespace/solvespace, 所代表的意義是, "假如"我們有能力看懂這個小型的參數式 2D/3D 電腦輔助繪圖系統的製作原理, 之後就可以客製化修改此一系統, 加入所要延伸的功能.

只是, 經過四百多天之後, 以下的編譯流程, 還能套用在最新的程式碼嗎?

"假如" 基本的參數式零組件建構軟體已經可以從使用者進階到陽春開發者, 那麼 https://github.com/Range-Software/range3 是否也能夠用類似的流程進行編譯與修改或延伸?

一旦, 協同產品開發者, 擁有最最基本可隨身的 CAD 與 CAE 套件之後, 就終於可以再結合 V-rep, 進行所謂創新產品的開發了嗎?




接下來, "假如"上述彈珠台的每一個立柱, 都裝上感測器, 且被彈珠碰撞後分別代表得分或扣分, "假如" 協同產品設計團隊能夠讓一套所謂具有學習或人工智慧的程式來發球, "它" 有機會可以越學越精準透過發球, 每次都取得彈珠檯遊戲的最高分嗎?

2017.12.25

在 MSYS2 環境編譯 Solvespace 


先前必須在 Ubuntu 或 Windows Visual Studio 環境中, 才能夠編譯 Windows 環境中的 Solvespace 執行檔情況, 在 2014 年 MSYS2 推出之後, 有了截然不同的改變.

MSYS2 建立 Windows 執行程式

MPV 首先發布在 Windows 環境中採用 MSYS2 執行原生編譯, 但是將所依賴的程式庫安裝在 MSYS2 環境中的方法, 並不適用於 Solvespace.

MSYS2 建立 solvespace.exe

在視窗環境, 利用 MSYS2 編譯 Solvespace, 目前已知可行方案為, 只採用 MSYS2 所提供的 gcc 編譯器與 mingw32-make 執行編譯及連結, 但前置處理 Solvespace 所需的 CMake, zlib 與 64 位元 d3dcompiler 程式, 都必須使用 Windows 原生版本. 而且從 Solvespace 下載原始程式後, 必須蓋掉 angle 中搜尋 d3dcompiler_43.dll, d3dcompiler_46.dll 與 d3dcompiler_47.dll 動態連結程式庫的設定.
至於以 CMake 及 mingw32-make 編譯連結得到的 zlib 程式庫, 則必須放入 MSYS2 系統 lib 目錄中, 如此, 一旦在 build 目錄中完成
1
2
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
mingw32-make
之後, 就可以結合 solvespace.exe, d3dcompiler_43.dll 與 libwinpthread-1.dll, 在 Windows 10 64 位元的環境中啟動執行.

Solvespack 倉儲

根據上述配置所完成的 Solvespace, 專供 KMOLab 程式開發使用, 倉儲位於 Solvespack.

參考資料

下載 kmol_2019.7z

下載 nodejs_with_ungit.7z

p37_adv.7z (下載 5GB, 解開 15 GB)

Qt.7z (下載 8GB, 解開 21 GB)

Solvespace_kmol_2019.7z (100MB)

編譯 Solvespace 流程:

git clone --recursive  https://github.com/solvespace/solvespace

cd solvespace

mkdir build

cd build

cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release

mingw32-make

cd bin

solvespace.exe

listdlls64 solvespace.exe

複製執行 Solvespace.exe 所需 dll 或設法將程式庫與 exe 綁定


Friday, February 22, 2019

Solvespace Binary STL export to ASCII STL

Solvespace 零件檔案轉出 Binary STL 格式, 利用下列 Python 程式轉為 Binary STL 格式後, 轉進 Range3 系統中.


import struct
normals = []
points = []
triangles = []
triangle_number = 0
def load_binary_stl(fp):
    '''
    二位元 STL 檔案格式如下:
    檔案標頭共有 80 個字元(bytes), 內容通常省略, 但是內容不可使用 solid, 以免與文字檔案 STL 混淆
    UINT8[80] – Header
    UINT32 – Number of triangles (I:佔 4 bytes 的 unsigned integer)
 
    foreach triangle
    REAL32[3] – Normal vector (f:每一座標分量為一佔 4 bytes 的 float, 共佔 12 bytes)
    REAL32[3] – Vertex 1
    REAL32[3] – Vertex 2
    REAL32[3] – Vertex 3
    UINT16 – Attribute byte count (H:兩個 bytes 的 unsigned short, 表示 attribute byte count)
    end
 
    '''
    # 已經在外部開檔
    #fp=open(filename,'rb')
    header=fp.read(80)
    triangle_number = struct.unpack('I',fp.read(4))[0]
    #print(triangle_number)
    count=0
    while True:
        try:
            p=fp.read(12)
            if len(p)==12:
                n=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                normals.append(n)
                l = len(points)
                #print(n)
            p=fp.read(12)
            if len(p)==12:
                p1=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                points.append(p1)
                #print(p1)
            p=fp.read(12)
            if len(p)==12:
                p2=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                points.append(p2)
            p=fp.read(12)
            if len(p)==12:
                p3=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                points.append(p3)
                triangles.append((l, l+1, l+2))
            # 使用 count 來計算三角形平面個數
            # triangle_number 為 STL 檔案中的三角形個數
            count += 1
            #print(count)
            # 在前面 12*4 個 bytes 的 normal 與三個點資料後, 為
            # 一個 2 bytes 長的 unsigned short, 其值為零, 為 attribute
            fp.read(2)
            # 讀完所有三角平面後, 即跳出 while
            if count > triangle_number:
                break
        except EOFError:
            break
    #fp.close()
def read_length(f):
    length = struct.unpack("@i", f.read(4))
    return length[0]
def read_header(f):
    f.seek(f.tell()+80)
def write_as_ascii(outfilename):
    f = open(outfilename, "w")
    f.write ("solid "+outfilename+"\n")
    for n  in range(len(triangles)):
        f.write ("facet normal {} {} {}\n".format(normals[n][0],normals[n][1],normals[n][2]))
        f.write ("outer loop\n")
        f.write ("vertex {} {} {}\n".format(points[triangles[n][0]][0],points[triangles[n][0]][1],points[triangles[n][0]][2]))
        f.write ("vertex {} {} {}\n".format(points[triangles[n][1]][0],points[triangles[n][1]][1],points[triangles[n][1]][2]))
        f.write ("vertex {} {} {}\n".format(points[triangles[n][2]][0],points[triangles[n][2]][1],points[triangles[n][2]][2]))
        f.write ("endloop\n")
        f.write ("endfacet\n")
    f.write ("endsolid "+outfilename+"\n")
    f.close()
def main():
    infilename = "binary1.stl"
    outfilename = "ascii1.stl"
    try:
        f = open(infilename, "rb")
        #read_header(f)
        #l = read_length(f)
        try:
            load_binary_stl(f)
            l = len(normals)
        except Exception as e:
            print("Exception",e)
        print(len(normals), len(points), len(triangles), l)
        write_as_ascii(outfilename)
        print("done")
    except Exception as e:
        print(e)
if __name__ == '__main__':
    main()

其他相關程式:

建立 Binary STL 零件檔案:

#coding: utf-8
import struct
 
class StLFacet:
    def __init__(self, normal, v1, v2, v3, att_bc=0):
        self.coords = [normal, v1, v2, v3]
        self.att_bc = att_bc
 
class StL:
    def __init__(self, header):
        self.header = header
        self.facets = []
    def add_facet(self, facet):
        self.facets.append(facet)
    def get_binary(self):
        # 原先 2.0 的版本
        #out = ['%-80.80s' % self.header]
        # 改為 Python 3.0 格式
        # 第一行標頭的格式
        header = ['%-80.80s' % self.header][0]
        # 利用 bytes() 將標頭字串轉為二位元資料
        out = [bytes(header,encoding="utf-8")]
        # 接著則計算三角形面的數量, 並以二位元長整數格式存檔
        out.append(struct.pack('L',len(self.facets)))
        # 接著則依照法線向量與三個點座標的格式, 分別以浮點數格式進行資料附加
        for f in self.facets:
            for coord in f.coords:
                out.append(struct.pack('3f', *coord))
            # att_bc 則內定為 0
            out.append(struct.pack('H', f.att_bc))
        return b"".join(out)
 
def test():
    stl=StL('Header ...')
    stl.add_facet(StLFacet((0.,0.,1.),(0.,0.,0.),(1.,0.,0.),(0.,1.,0.)))
    stl.add_facet(StLFacet((0.,0.,1.),(1.,0.,0.),(1.,1.,0.),(0.,1.,0.)))
    # 第二個平面
    stl.add_facet(StLFacet((0.,-1.,0.),(0.,0.,0.),(0.,0.,-1.),(1.,0.,-1.)))
    stl.add_facet(StLFacet((0.,-1.,0.),(0.,0.,0.),(1.,0.,-1.),(1.,0.,0.)))
    return stl.get_binary()
 
# 指定存為 binary 格式檔案
stlfile = open("test.stl", "wb")
stlcontent = test()
stlfile.write(stlcontent)

PyGame STL viewer:
#coding: utf-8
# STL viewer 原始檔案來自
# University of Wuppertal - http://mbi-wiki.uni-wuppertal.de/wordpress/
# Modified by Uli Eggersmann
# Binary STL 資料讀取原始作者 Oliver Marks - http://www.linux.com
# 原始檔案僅讀取 Text STL 零件檔案
# 2011 Fall 由 KMOL 新增 Binary STL 零件檔案讀取
 
from visual import scene, color, materials, faces, points
import os, struct
 
#file ="ritzel.stl"
 
file ="binary.stl"
 
scene.width = 400
scene.height = 400
scene.background = color.white # black
# 視窗標題取自 cvisual.pyd, 不可使用中文
scene.title = "STLViewer in VPython"
 
print ("利用滑鼠右鍵旋轉")
print ("滑鼠左右鍵同時按下後移動, 可以縮放畫面")
 
# Read STL file, only use vertex-line with xyz coordinates
list = []
 
#load stl file detects if the file is a text file or binary file
def load_stl(filename):
    #read start of file to determine if its a binay stl file or a ascii stl file
    fp=open(filename,'rb')
    header=fp.read(80)
    filetype=header[0:5]
    # 這裡必須要能夠分辨二位元字串與文字字串
    #print (type(filetype))
    #print (filetype)
    fp.close()
 
    # for Python 3
    if filetype==b'solid':
    # for Python 2
    #if filetype=='solid':
        print ("讀取文字檔案格式:"+str(filename))
        load_text_stl(filename)
    else:
        print ("讀取二位元檔案格式:"+str(filename,))
        load_binary_stl(filename)
 
#load binary stl file check wikipedia for the binary layout of the file
#we use the struct library to read in and convert binary data into a format we can use
def load_binary_stl(filename):
    '''
    二位元 STL 檔案格式如下:
    檔案標頭共有 80 個字元(bytes), 內容通常省略, 但是內容不可使用 solid, 以免與文字檔案 STL 混淆
    UINT8[80] – Header
    UINT32 – Number of triangles (I:佔 4 bytes 的 unsigned integer)
 
    foreach triangle
    REAL32[3] – Normal vector (f:每一座標分量為一佔 4 bytes 的 float, 共佔 12 bytes)
    REAL32[3] – Vertex 1
    REAL32[3] – Vertex 2
    REAL32[3] – Vertex 3
    UINT16 – Attribute byte count (H:兩個 bytes 的 unsigned short, 表示 attribute byte count)
    end
 
    '''
    global list
 
    fp=open(filename,'rb')
    header=fp.read(80)
 
    triangle_number = struct.unpack('I',fp.read(4))[0]
    count=0
    while True:
        try:
            p=fp.read(12)
            if len(p)==12:
                n=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
 
            p=fp.read(12)
            if len(p)==12:
                p1=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                list.append(p1)
            p=fp.read(12)
            if len(p)==12:
                p2=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                list.append(p2)
            p=fp.read(12)
            if len(p)==12:
                p3=[struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]]
                list.append(p3)
            # 使用 count 來計算三角形平面個數
            # triangle_number 為 STL 檔案中的三角形個數
            count += 1
            # 在前面 12*4 個 bytes 的 normal 與三個點資料後, 為
            # 一個 2 bytes 長的 unsigned short, 其值為零, 為 attribute
            fp.read(2)
            # 讀完所有三角平面後, 即跳出 while
            if count > triangle_number:
                break
        except EOFError:
            break
    fp.close()
 
 
def load_text_stl(filename):
    global list
    for dataline in open(filename,"r").readlines():
        if not dataline.strip(): # skip blank lines
            continue
        field = dataline.split() # split with no argument makes the right place!
        if field[0] == "vertex":
            list.append([float(x) for x in field[1:4]])
            #print (list)
            #break
            #for x in field[1:4]:
                #print(x)
 
load_stl(os.path.abspath('')+'/'+file)
 
 
# Graphics
model = faces(pos=list, color=(0.8,0.8,0.8),
              material=materials.plastic) # creates triangles
# 請注意, 這裡並沒有使用 STL 檔案中的平面 normal, 而是利用 VPython make_normals() 產生
model.make_normals() # creates plane normals
model.smooth(0.93) # smooths the edges
# = AllepunkteSTL points (pos = list, size = 3, color = Color.Black) # generates points 

PyGame 與 OpenGL 檢視 STL
#coding: utf8
# source: https://www.linux.com/community/blogs/133-general-linux/291889
import os
import struct
 
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame
from pygame.locals import *
 
#class for a 3d point
class createpoint:
    def __init__(self,p,c=(1,0,0)):
        self.point_size=0.5
        self.color=c
        self.x=p[0]
        self.y=p[1]
        self.z=p[2]
 
    def glvertex(self):
        glVertex3f(self.x,self.y,self.z)
 
#class for a 3d face on a model
class createtriangle:
    points=None
    normal=None
 
    def __init__(self,p1,p2,p3,n=None):
        #3 points of the triangle
        self.points=createpoint(p1),createpoint(p2),createpoint(p3)
 
        #triangles normal
        self.normal=createpoint(self.calculate_normal(self.points[0],self.points[1],self.points[2]))#(0,1,0)#
 
    #calculate vector / edge
    def calculate_vector(self,p1,p2):
        return -p1.x+p2.x,-p1.y+p2.y,-p1.z+p2.z
 
    def calculate_normal(self,p1,p2,p3):
        a=self.calculate_vector(p3,p2)
        b=self.calculate_vector(p3,p1)
        #calculate the cross product returns a vector
        return self.cross_product(a,b)    
 
    def cross_product(self,p1,p2):
        return (p1[1]*p2[2]-p2[1]*p1[2]) , (p1[2]*p2[0])-(p2[2]*p1[0]) , (p1[0]*p2[1])-(p2[0]*p1[1])
 
class loader:
    model=[]
 
    #return the faces of the triangles
    def get_triangles(self):
        if self.model:
            for face in self.model:
                yield face
 
    #draw the models faces
    def draw(self):
        glBegin(GL_TRIANGLES)
        for tri in self.get_triangles():
            glNormal3f(tri.normal.x,tri.normal.y,tri.normal.z)
            glVertex3f(tri.points[0].x,tri.points[0].y,tri.points[0].z)
            glVertex3f(tri.points[1].x,tri.points[1].y,tri.points[1].z)
            glVertex3f(tri.points[2].x,tri.points[2].y,tri.points[2].z)
        glEnd()
 
    #load stl file detects if the file is a text file or binary file
    def load_stl(self,filename):
        #read start of file to determine if its a binay stl file or a ascii stl file
        fp=open(filename,'rb')
        h=fp.read(80)
        type=h[0:5]
        fp.close()
 
        if type=='solid':
            print ("reading text file"+str(filename))
            self.load_text_stl(filename)
        else:
            print ("reading binary stl file "+str(filename,))
            self.load_binary_stl(filename)
 
    #read text stl match keywords to grab the points to build the model
    def load_text_stl(self,filename):
        fp=open(filename,'r')
 
        for line in fp.readlines():
            words=line.split()
            if len(words)>0:
                if words[0]=='solid':
                    self.name=words[1]
 
                if words[0]=='facet':
                    center=[0.0,0.0,0.0]
                    triangle=[]
                    normal=(eval(words[2]),eval(words[3]),eval(words[4]))
 
                if words[0]=='vertex':
                    triangle.append((eval(words[1]),eval(words[2]),eval(words[3])))
 
 
                if words[0]=='endloop':
                    #make sure we got the correct number of values before storing
                    if len(triangle)==3:
                        self.model.append(createtriangle(triangle[0],triangle[1],triangle[2],normal))
        fp.close()
 
    #load binary stl file check wikipedia for the binary layout of the file
    #we use the struct library to read in and convert binary data into a format we can use
    def load_binary_stl(self,filename):
        fp=open(filename,'rb')
        h=fp.read(80)
 
        l=struct.unpack('I',fp.read(4))[0]
        count=0
        while True:
            try:
                p=fp.read(12)
                if len(p)==12:
                    n=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]
 
                p=fp.read(12)
                if len(p)==12:
                    p1=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]
 
                p=fp.read(12)
                if len(p)==12:
                    p2=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]
 
                p=fp.read(12)
                if len(p)==12:
                    p3=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0]
 
                new_tri=(n,p1,p2,p3)
 
                if len(new_tri)==4:
                    tri=createtriangle(p1,p2,p3,n)
                    self.model.append(tri)
                count+=1
                fp.read(2)
 
                if len(p)==0:
                    break
            except EOFError:
                break
        fp.close()
 
 
 
class draw_scene:
    def __init__(self,style=1):
        #create a model instance and
        self.model1=loader()
        #self.model1.load_stl(os.path.abspath('')+'/text.stl')
        self.model1.load_stl(os.path.abspath('')+'/cube.stl')
        self.init_shading()
 
 
    #solid model with a light / shading
    def init_shading(self):
        glShadeModel(GL_SMOOTH)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glClearDepth(1.0)
        glEnable(GL_DEPTH_TEST)
        glShadeModel(GL_SMOOTH) 
        glDepthFunc(GL_LEQUAL)
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
 
        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)   
        glLight(GL_LIGHT0, GL_POSITION,  (0, 1, 1, 0))      
        glMatrixMode(GL_MODELVIEW)
 
    def resize(self, width, height):
        if height==0:
            height=1
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45, 1.0*width/height, 0.1, 100.0)
        #gluLookAt(0.0,0.0,45.0,0,0,0,0,40.0,0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
 
 
    def init(self):
        glShadeModel(GL_SMOOTH)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glClearDepth(1.0)
        glEnable(GL_DEPTH_TEST)
        glShadeModel(GL_SMOOTH) 
        glDepthFunc(GL_LEQUAL)
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
 
 
        glEnable(GL_COLOR_MATERIAL)
 
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)   
        glLight(GL_LIGHT0, GL_POSITION,  (0, 1, 1, 0))
 
        glMatrixMode(GL_MODELVIEW)
 
    def draw(self):
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
 
        glTranslatef(0.0,-26.0, -100.0)
        self.model1.draw()
 
#main program loop
def main():
    #initalize pygame
    pygame.init()
    pygame.display.set_mode((640,480), OPENGL|DOUBLEBUF)
 
    #setup the open gl scene
    scene=draw_scene()
    scene.resize(640,480)
 
    frames = 0
    ticks = pygame.time.get_ticks()
    while 1:
        event = pygame.event.poll()
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            break
 
        #draw the scene
        scene.draw()
        pygame.display.flip()
        frames = frames+1
 
    print ("fps:  %d" % ((frames*1000)/(pygame.time.get_ticks()-ticks)))
 
if __name__ == '__main__':
    main()

另一個 STL Writer:
#coding:utf-8
# source: http://code.activestate.com/recipes/578246-stl-writer/
 
import struct
 
ASCII_FACET = """facet normal 0 0 0
outer loop
vertex {face[0][0]:.4f} {face[0][1]:.4f} {face[0][2]:.4f}
vertex {face[1][0]:.4f} {face[1][1]:.4f} {face[1][2]:.4f}
vertex {face[2][0]:.4f} {face[2][1]:.4f} {face[2][2]:.4f}
endloop
endfacet
"""
 
BINARY_HEADER ="80sI"
BINARY_FACET = "12fH"
 
class ASCII_STL_Writer:
    """ Export 3D objects build of 3 or 4 vertices as ASCII STL file.
    """
    def __init__(self, stream):
        self.fp = stream
        self._write_header()
 
    def _write_header(self):
        self.fp.write("solid python\n")
 
    def close(self):
        self.fp.write("endsolid python\n")
 
    def _write(self, face):
        self.fp.write(ASCII_FACET.format(face=face))
 
    def _split(self, face):
        p1, p2, p3, p4 = face
        return (p1, p2, p3), (p3, p4, p1)
 
    def add_face(self, face):
        """ Add one face with 3 or 4 vertices. """
        if len(face) == 4:
            face1, face2 = self._split(face)
            self._write(face1)
            self._write(face2)
        elif len(face) == 3:
            self._write(face)
        else:
            raise ValueError('only 3 or 4 vertices for each face')
 
    def add_faces(self, faces):
        """ Add many faces. """
        for face in faces:
            self.add_face(face)
 
class Binary_STL_Writer(ASCII_STL_Writer):
    """ Export 3D objects build of 3 or 4 vertices as binary STL file.
    """
    def __init__(self, stream):
        self.counter = 0
        super(Binary_STL_Writer, self).__init__(stream)
 
    def close(self):
        self._write_header()
 
    def _write_header(self):
        self.fp.seek(0)
        self.fp.write(struct.pack(BINARY_HEADER, b'Python Binary STL Writer', self.counter))
 
    def _write(self, face):
        self.counter += 1
        data = [
            0., 0., 0.,
            face[0][0], face[0][1], face[0][2],
            face[1][0], face[1][1], face[1][2],
            face[2][0], face[2][1], face[2][2],
            0
        ]
        self.fp.write(struct.pack(BINARY_FACET, *data))
 
 
def example():
    def get_cube():
        # cube corner points
        s = 3.
        p1 = (0, 0, 0)
        p2 = (0, 0, s)
        p3 = (0, s, 0)
        p4 = (0, s, s)
        p5 = (s, 0, 0)
        p6 = (s, 0, s)
        p7 = (s, s, 0)
        p8 = (s, s, s)
 
        # define the 6 cube faces
        # faces just lists of 3 or 4 vertices
        return [
            [p1, p5, p7, p3],
            [p1, p5, p6, p2],
            [p5, p7, p8, p6],
            [p7, p8, p4, p3],
            [p1, p3, p4, p2],
            [p2, p6, p8, p4],
        ]
    '''
    for writing ASCII STL cube file
    with open('cube_ascii.stl', 'w') as fp:
        writer = ASCII_STL_Writer(fp)
        writer.add_faces(get_cube())
        writer.close()
    '''
    with open('cube_bin.stl', 'wb') as fp:
        writer = Binary_STL_Writer(fp)
        writer.add_faces(get_cube())
        writer.close()
 
if __name__ == '__main__':
    example()

NX12

NX 12 Help https://docs.plm.automation.siemens.com/tdoc/nx/12/nx_help Python related https://docs.plm.automation.siemens.com/tdoc/nx/...