0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SIRIS > Gaussian Random Sphere > vtk.outからSTLファイルを生成、GitHubでレンダリングする流れと実装

Last updated at Posted at 2018-05-27
動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04.4 LTS desktop amd64
TensorFlow v1.7.0
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
gnustep-gui-runtime v0.24.0-3.1
PyMieScatt v1.7.0

概要

今回

  • SIRISの出力vtk.outからTrianglesの座標情報を読込む
  • 読込んだTrianglesの座標情報を元に、格子状のdipole配置で表現 (以下、**「dipole表現」**と記載)
  • GitHubに上げてぐりぐり

処理の流れ

  1. vtk.outを読込み、dipole表現する
    • volfil_vtkShape_180526.py
      • 入力: vtk.out
      • import VTKReader_180526
      • 出力: dipole_180526.res
  2. dipole表現に対して、STLファイル形式にする
    • make_cubeGroup_180520.py
      • 入力: dipole_180526.res
      • 出力: cubeGroup_180527_t0805.stl
  3. GitHubにpush

実装

VTKReader_180526.py v0.2

  • VTK形式ファイルを読む
VTKReader_180526.py
import numpy as np
import sys

'''
v0.2 May, 27, 2018
  - fix bug: get_triangle_coordinate() returned [number of vertices] mistakenly
  - rename split_to_triangles() to get_triangle_coordinate()
v0.1 May, 26, 2018
  - branched
=== branched from [test_read_vtkout_180526.py] ===
v0.2 May, 26, 2018
  - add Test_main()
  - add get_gaussian_sphere_vertices()
  - add read_polygons_vertices()
  - add split_to_triangles()
  - read polygonIdxs[]
  - read vertices[]
  - add get_polygons_number()
v0.1 May, 26, 2018
  - add get_vertices_number()
'''


def get_vertices_number(instr):
    # instr: e.g. 'POINTS    578 float'
    return int(instr.split()[1])


def get_polygons_number(instr):
    # instr: e.g. 'POLYGONS    1152   4608'
    return int(instr.split()[1])


def get_triangle_coordinate(polygonIndices, vertices):
    ret = []
    for elem in polygonIndices:
        # get vertex indices from elem
        # e.g. "           3           2           6           7"
        # where the 1st [3] is the number of polygon vertices
        ret += [[int(elem[1]), int(elem[2]), int(elem[3])]]
    return ret


def read_polygons_vertices(infile):
    # key to find the corresponding line
    KEY_VERTICES = 'POINTS'
    KEY_POLYGONS = 'POLYGONS'

    dat = np.genfromtxt(infile, dtype='str', delimiter=',')

    cdwnVert = -1  # countdown to read [vertices], >0: read
    vertices = []  # 2d array having (x,y,z) for each
    cdwnPoly = -1  # countdown to read [Polygons], >0: read
    polygonIdxs = []
    for elem in dat:
        if cdwnVert > 0:
            cdwnVert -= 1
            vertices += [elem.split()]
        if cdwnPoly > 0:
            cdwnPoly -= 1
            polygonIdxs += [elem.split()]
        if KEY_VERTICES in elem:
            numVert = get_vertices_number(elem)
            cdwnVert = numVert
        if KEY_POLYGONS in elem:
            numPlygn = get_polygons_number(elem)
            cdwnPoly = numPlygn
    return polygonIdxs, vertices


def get_gaussian_sphere_vertices(infile):
    plygnIdx, verts = read_polygons_vertices(infile)

    tris = get_triangle_coordinate(plygnIdx, verts)

    ret = []
    for atri in tris:
        vrt1 = [float(x) for x in verts[atri[0]]]
        vrt2 = [float(x) for x in verts[atri[1]]]
        vrt3 = [float(x) for x in verts[atri[2]]]
        ret += [np.array([vrt1, vrt2, vrt3])]
    return np.array(ret)


def Test_main():
    IN_FILE = 'vtk.out'  # output of [G-sphere]

    vrts = get_gaussian_sphere_vertices(IN_FILE)
    print(vrts[0])
    print(vrts[-1])


if __name__ == '__main__':
    Test_main()

volfil_vtkShape_180526.py v0.2

  • vtk.outをもとにdipole表現する
  • dpl = get_dipole_positions_in_rectangle(expand=2.0, numdiv=20)
    • expand=2.0: 対象領域を[-2.0, 2.0]とする (2.0を含む)
    • numdiv=20: 対象領域を20x20x20のdipoleで表現する
    • expand, numdivは対象形状、分解能に合わせて変更して使う
volfil_vtkShape_180526.py
import numpy as np
import geometry_intersection_3D_180513 as GI3
import VTKReader_180526 as VTKRD
import sys
import os


'''
v0.2 May, 27, 2018
  - get_dipole_positions_in_rectangle*) takes [numdiv] arg
v0.1 May, 26, 2018
  - import [VTKReader_180526.py]
=== branched from [volfil_tetrahedron_180519.py] ===
v0.2 May, 20, 2018
  - output as file for reading with Numpy genfromtxt()
    + add [OUTPUT]
    + remove [OUTPUT] before file save
v0.1 May, 19, 2018
  - add check_vertex_intersecting_ray()
  - import [geometry_intersection_3D_180513]
  - add get_dipole_positions_in_rectangle()
  - add get_regular_tetrahedron_vertices()
'''

OUTFILE = 'dipole_180526.res'  # for Numpy genfromtxt()


def get_regular_tetrahedron_vertices(expand=1.0):
    vrt1 = np.array([expand, expand, expand])  # vertex
    vrt2 = np.array([-expand, -expand, expand])
    vrt3 = np.array([-expand, expand, -expand])
    vrt4 = np.array([expand, -expand, -expand])

    ret = []
    ret += [np.array([vrt1, vrt2, vrt3])]
    ret += [np.array([vrt1, vrt3, vrt4])]
    ret += [np.array([vrt2, vrt3, vrt4])]
    ret += [np.array([vrt1, vrt2, vrt4])]

    return np.array(ret)


def get_dipole_positions_in_rectangle(expand=5.0, numdiv=9):
    mx = np.linspace(-expand, expand, numdiv)
    my = np.linspace(-expand, expand, numdiv)
    mz = np.linspace(-expand, expand, numdiv)
    ret = []
    for idx in range(len(mx)):
        for idy in range(len(my)):
            for idz in range(len(mz)):
                ret += [np.array([mx[idx], my[idy], mz[idz]])]
    return np.array(ret)


def check_vertex_intersecting_ray(start, end, vertices):
    ray = np.array([start, end])
    for vertex in vertices:
        res, retI = GI3.check_intersection(ray, vertex)
        isIntsct = GI3.check_reachingIntersection(ray, vertex)
        if isIntsct:
            return False
    return True


IN_FILE = 'vtk.out'
vtkshp = VTKRD.get_gaussian_sphere_vertices(IN_FILE)
dpl = get_dipole_positions_in_rectangle(expand=2.0, numdiv=20)

startary = np.array([0, 0, 0])

os.remove(OUTFILE)
with open(OUTFILE, 'ab') as wfp:
    for elem in dpl:
        res = check_vertex_intersecting_ray(startary, elem, vtkshp)
        if res:
            print("[%f, %f, %f]," % (elem[0], elem[1], elem[2]))
            wrk = [elem]  # to avoid element-wise-LF for 1-D array
            np.savetxt(wfp, wrk, fmt='%.7f', delimiter=' ')

make_cubeGroup_180520.py v0.2

  • dipole表現を元にSTLファイルを生成する
make_cubeGroup_180520.py
import numpy as np
import sys

import STLWriter as STLWR
# STLWriter
# code from
# http://code.activestate.com/recipes/578246/
# by Manfred Moitzi
# (renamed as STLWriter.py from recipe-578246-1.py)

#

'''
v0.2 May, 26, 2018
  - change [OUT_FILE]
v0.1 May, 20, 2018
  - read dipole positions from [IN_FILE]
  - add python_list_add()
  - get_cube() takes [size] arg
  - add make_cubeGroup()
'''


def python_list_add(in1, in2):
    wrk = np.array(in1) + np.array(in2)
    return wrk.tolist()


def make_cubeGroup():
    def get_cube(size=3, origin=[0, 0, 0]):
        # cube corner points
        s = size
        p1 = python_list_add(origin, (0, 0, 0))
        p2 = python_list_add(origin, (0, 0, s))
        p3 = python_list_add(origin, (0, s, 0))
        p4 = python_list_add(origin, (0, s, s))
        p5 = python_list_add(origin, (s, 0, 0))
        p6 = python_list_add(origin, (s, 0, s))
        p7 = python_list_add(origin, (s, s, 0))
        p8 = python_list_add(origin, (s, s, s))

        print(p1)

        # define the 6 cube faces
        # faces just lists of 3 or 4 vertices
        #
        # [NOTE]
        # vertices must be defined [anticlockwise] to be seen on GitHub
        # otherwise, the face is not drawn
        #
        return [
            [p1, p3, p7, p5],  # bottom
            [p1, p5, p6, p2],
            [p5, p7, p8, p6],
            [p7, p3, p4, p8],  # rear
            [p1, p2, p4, p3],  # left
            [p2, p6, p8, p4],
        ]

    # 1. Regular Tetrahedra
    # IN_FILE = 'dipole_180520.res'  # from [volfil_tetrahedron_180519.py] v0.2
    # OUT_FILE = 'cubeGroup_180520_t0950.stl'
    # DIPOLE_SIZE = 5

    # 2. VTK from Gaussian Sphere code
    IN_FILE = 'dipole_180526.res'  # from [volfil_vtkShape_180526.py] v0.1
    # OUT_FILE = 'cubeGroup_180526_t1040.stl'
    OUT_FILE = 'cubeGroup_180527_t0805.stl'
    DIPOLE_SIZE = 0.25

    with open(IN_FILE, 'rb') as rfp:
        dipoles = np.genfromtxt(IN_FILE)

    with open(OUT_FILE, 'wb') as wfp:
        writer = STLWR.Binary_STL_Writer(wfp)

        for adipole in dipoles:
            cube = get_cube(DIPOLE_SIZE, adipole)
            writer.add_faces(cube)

        writer.close()
    print('OUT:', OUT_FILE)

if __name__ == '__main__':
    make_cubeGroup()

結果

結果 20x20x20

20x20x20: 7分20秒の処理 (volfil_vtkShape_180526.py)。
331 KBのSTLファイル。

make_cubeGroup_180520.pyの処理は数秒。

cubeGroup_180527_t0805.stl @ GitHub

処理時間はかかるが、閲覧時は「XXソフトが必要」なく、ある程度の性能のあるPC上で閲覧できる。

結果 40x40x40

分解能を上げてみた。

40x40x40: 52分25秒の処理。
4894 dipoleとなった。

cubeGroup_180527_t0935.stl @ GitHub

生成したパラメータでのGaussin Random Sphere形状の特徴が捉えやすくなった。

qiita.png

結果 80x80x80

80x80x80: 380分24秒の処理。
40,662 dipoleとなった。

(注意: 下記のファイルは23.3MBです。)

cubeGroup_180527_t1052.stl @ GitHub

qiita.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?