Графика, Plotly и STL

Автор Vitalij Lysanov, 15.01.20, 01:32:07

« предыдущая - следующая »

0 Пользователей и 1 гость просматривают эту тему.

Vitalij Lysanov




             Графика и Plotly

Про Plotly -- в завершении, а вначале вступление на тему -- мелочи, подробности, погружение.
Потому что будем пробовать прямую запись в html файл.

Мелочи  
Прочитал: 
<a href="https://habr.com/ru/post/483674/[/img]Как работают двоичные нейронные сети, и почему они будут популярными в 2020-м</a>
 и с учетом 
<a href="https://pycode.ru/2015/12/zhiznennyiy-tsikl-programmista/[/img]Жизненный цикл программиста. Михаил Донской</a>,
где говорят, что Ассемблер это уже плохо, Алгол еще хуже, а программировать в кодах -- это в самый раз. Для примера рассказывают, как делали шахматную программу.
Программировать в кодах это погружение по максимуму. И чем глубже, тем больше открывается возможностей.
Как проектировал испытательную станцию
Испытательная станция -- это камеры тепла, холода, вибростенды, ударные стенды. Нужно было проект составить на новое помещение. В проект заложили три ИВК на базе СМ с измерительными крейтами  и ЕС ЭВМ, это получилось половину станции и еще помещение для охлаждения ЕС.
На предмет необходимости такого оборудования на испытательной станции, это уже вопрос...
Ладно, смотрели, смотрели на все это. Большой начальник говорит пускай остается, на эти деньги что-нибудь другое купим. Иногда с вычислительного отдела спрашивали, кто это нарисовал? Все молчат.
Пару раз ездил к проектировщикам, ЕС 1840 добавили.
Котлован уже выкопали, столбы поставили. Потом 90 год и на этом месте развлекательный центр построили.
Это первый сигнал, что внизу тоже можно много решить, или пытаться решить. 
Второй сигнал 
Можно поискать в интернете, но по памяти.
Военный ходил по городу, и заступился за солдата, у которого были неприятности.
Разговорились, солдат спросил про фамилию и где служишь.
Идет время, приходит повышение офицеру, неожиданно, но пусть будет.
Потом еще повышение, уже выше командира по званию.
Потом приходит письмо с извинениями от писаря. Извините, дальше повышать сложно, это у другого писаря.
Это второй сигнал, что внизу тоже можно много решить.
Пример ближе к программированию
Звуковые карты были еще в дефиците, нужно было много вводить текста в таблицы, и чтобы меньше нагружать глаза, нашел программу, которая на пищалку говорила текст. Как всегда, платная. В рекламных целях конечно при запуске говорила текст. Дальше просто, нашел этот текст в программе, открывал программу в текстовом режиме и записывал нужный текст. При запуске программа говорила то, что надо.
Пример ближе к современности
Гифки в сайтах и форумах хорошая вещь. Все крутится, вращается, перемещается, например,
 

А есть интерактивные рисунки, можно вращать, приближать и много еще что можно, например, (здесь ничего не вращается, это просто картинка, вращать можно после загрузки html файла)

Это так выводит Plotly.
Это треугольники между точками. Одни точки идут по вертикальной прямой, вторые точки идут по наклонной кривой.
Если навести, в белом окошке значения в точке.
Справа вверху это управление изображением. Вращать, приближать, вернуть в исходное и пр.
Про Plotly узнал из: 
<a href="https://habr.com/ru/post/480660/[/img]Визуализация странных аттракторов в Plotly -- это шедеврально</a>
Треугольники формата STL программа тоже должно рисовать, но пока?
Зато просто треугольники рисует хорошо и к тому же сохраняет в формате html.  Рисунок выше это изображение на экране при загрузке файла html. Сразу можно сказать, что размер 3 мегабайта это минимум, который все обеспечивает для рисования и вращения. Можно, наверное оставить только вращение, тогда размер будет меньше. Изучать нужно ...


 
 <a href="https://drive.google.com/open?id=1vDsEjJZJ87LFqP5HAQlAdoj4mKIipwWL[/img]ssss_tre.html</a>




Поэтому, вспоминая про тему погружения в первоисточники, смотрим в текстовом режиме файл html и находим массив данных, изменяя который можем рисовать все что угодно, можно и в Excel сформировать файл данных.
Дальше вручную или программой вставляем в файл данные в файл html. Вручную, это если несколько точек, а программой можно и 10000 треугольников построить. На каждый треугольник шесть цифр, причем три цифры -- это целые числа, номера точек для отрисовки треугольника. 

  
<source>
from google.colab import drive
drive.mount('/content/drive/')
working_path = "/content/drive/My Drive/"</source>

 
 
 
<source>
import plotly.graph_objects as go</source>

 
<source>
fig = go.Figure(data=[
    go.Mesh 3d(
        x=[0, 1, 2, 0],
        y=[0, 0, 1, 2],
        z=[0, 2, 0, 1],
        colorbar_title='z',
        #cv='magenta',
        colorscale=[[0, 'rgb (0, 0, 255)'],
                    [0.5, 'rgb (0, 255, 0)'],
                    [1.0, 'rgb (255, 0, 0)']],
        # Intensity of each vertex, which will be interpolated and color-coded
        intensity=[0, 1, 1, 1, 1, 1],
        # i, j and k give the vertices of triangles
        # here we represent the 4 triangles of the tetrahedron surface
        i=[0, 0],
        j=[1, 2],
        k=[2, 3],
        name='y',
        showscale=True
    )
])</source>

 
<source>
fig.show()
fig.write_html(working_path +'file_12_rgb.html')</source>

Если записывать на диск, нужно пару раз в день подтверждать аккаунт.
Без записи на диск можно просто:
<source>
import plotly.graph_objects as go</source>

 
<source>
fig = go.Figure(data=[
    go.Mesh3d(
        x=[0, 1, 2, 0],
        y=[0, 0, 1, 2],
        z=[0, 2, 0, 1],
        colorbar_title='z',
        #cv='magenta',
        colorscale=[[0, 'rgb (0, 0, 255)'],
                    [0.5, 'rgb (0, 255, 0)'],
                    [1.0, 'rgb (255, 0, 0)']],
        # Intensity of each vertex, which will be interpolated and color-coded
        intensity=[0, 1, 1, 1, 1, 1],
        # i, j and k give the vertices of triangles
        # here we represent the 4 triangles of the tetrahedron surface
        i=[0, 0],
        j=[1, 2],
        k=[2, 3],
        name='y',
        showscale=True
    )
])</source>

 
<source>
fig.show()</source>

И нарисует картинку, которую можно вращать приближать и ...
Теперь смотрим в текстовом режиме файл html:
[{"colorbar": {"title": {"text": "z"}}, 
colorscale: [[0, "rgb (0, 0, 255)"], [0.5, "rgb (0, 255, 0)"], [1.0, "rgb (255, 0, 0)"]], 
 
i: [0, 0], "intensity": [0, 1, 1, 1, 1, 1], 
j: [1, 2], 
k: [2, 3], "name": 
 
y, "showscale": true, "type": "mesh3d", 
 
x: [0, 1, 2, 0], 
y: [0, 0, 1, 2], 
z: [0, 2, 0, 1]}],
Все то-же самое, только это немного приукрасили, в действительности, для экономии, все идет подряд.
Если нужно два объекта, может даже разные объекты, линии и треугольники, тогда:
 <source>
from google.colab import drive
drive.mount('/content/drive/')
working_path = "/content/drive/My Drive/"</source>

 
<source>
import plotly.graph_objects as go</source>

 
<source>
data=[
    go.Mesh3d(
        x=[0, 1, 2, 0],
        y=[0, 0, 1, 2],
        z=[0, 2, 0, 1],
        colorbar_title='z',
        #cv='magenta',
        colorscale=[[0, 'rgb (0, 0, 255)'],
                    [0.5, 'rgb (0, 255, 0)'],
                    [1.0, 'rgb (255, 0, 0)']],
        # Intensity of each vertex, which will be interpolated and color-coded
        intensity=[0, 1, 1, 1, 1, 1],
        # i, j and k give the vertices of triangles
        # here we represent the 4 triangles of the tetrahedron surface
        i=[0, 0],
        j=[1, 2],
        k=[2, 3],
        name='y',
        showscale=True
    )
]</source>

 
<source>
data1=[
    go.Mesh3d(
        x=[0, 1, 2, 0],
        y=[0, 0, 1, 2],
        z=[10, 12, 10, 11],
        colorbar_title='z',
        #cv='magenta',
        colorscale=[[0, 'rgb (0, 0, 255)'],
                    [0.5, 'rgb (0, 255, 0)'],
                    [1.0, 'rgb (255, 0, 0)']],
        # Intensity of each vertex, which will be interpolated and color-coded
        intensity=[0, 1, 1, 1, 1, 1],
        # i, j and k give the vertices of triangles
        # here we represent the 4 triangles of the tetrahedron surface
        i=[0, 0],
        j=[1, 2],
        k=[2, 3],
        name='y',
        showscale=True
    )
]</source>

 
<source>
fig = go.Figure(data+data1)</source>

 
<source>
fig.show()
fig.write_html(working_path +'2tr_file_12_rgb.html')


[{"colorbar": {"title": {"text": "z"}}, 
colorscale: [[0, "rgb (0, 0, 255)"], [0.5, "rgb (0, 255, 0)"], [1.0, "rgb (255, 0, 0)"]], </source>

 
<source>
i: [0, 0], 
intensity: [0, 1, 1, 1, 1, 1], 
j: [1, 2], 
k: [2, 3], </source>

 
<source>
name:"y", "showscale": true, "type": "mesh3d", </source>

 
<source>
x: [0, 1, 2, 0], 
y: [0, 0, 1, 2], 
z: [0, 2, 0, 1]}, </source>

 
 
<source>
{"colorbar": {"title": {"text": "z"}}, 
colorscale: [[0, "rgb (0, 0, 255)"], [0.5, "rgb (0, 255, 0)"], [1.0, "rgb (255, 0, 0)"]], </source>

 
<source>
i: [0, 0], 
intensity: [0, 1, 1, 1, 1, 1], 
j: [1, 2], 
k: [2, 3], </source>

 
<source>
name: "y", "showscale": true, "type": "mesh3d", </source>

 
<source>
x: [0, 1, 2, 0], 
y: [0, 0, 1, 2], 
z: [10, 12, 10, 11]}],</source>
 
 
 
Две группы -- это как два объекта, объектов нужно поменьше. Желательно все расположить в одной группе.

Также можно управлять цветом каждой точки.

Выходной файл можно сделать неотличимым от файла, сформированного Plotly.


Ниже программа формирующая данные по двум функциям. Просто строит треугольники между двумя кривыми.

Еще нужны два файла, один файл - это текст html до начала данных, второй это информация после блока данных. Это все формируется и записывается в любом текстовом редакторе.

 
<source>
import numpy as np</source>

 
<source>
n=68</source>

 
<source>
t = np.linspace(0, 1, n)
inten=np.linspace(0, 1, 2*n-2)</source>

 
 
<source>
tsi=np.sin(t)
tco=np.cos(t)</source>

 
<source>
tsi_2=np.linspace(0, 0, n)
tco_2=np.linspace(0, 0, n)</source>

 
<source>
i=np.arange(0,n-2,1, dtype=int)
j=np.arange(1,n-1,1, dtype=int)
k=np.arange(2,n,1, dtype=int)</source>

 
 
<source>
import math</source>

 
<source>
itens=iii='"'+'intensity'+'"'+": ["</source>

 
<source>
iii='"'+'i'+'"'+": ["
jjj='"'+'j'+'"'+": ["
kkk='"'+'k'+'"'+": ["</source>

 
 
<source>
xxx='"'+'x'+'"'+": ["
yyy='"'+'y'+'"'+": ["
zzz='"'+'z'+'"'+": ["</source>

 
 
 
<source>
for nom in range(0,2*n-4,1):
   iii=iii+str(int(nom))+", "
iii=iii+"],"</source>

 
<source>
for nom in range(1,2*n-3,1):</source>

 
<source>
   if nom % 2 == 0:
       jjj=jjj+str(int(1+nom))+", "
   else:
       jjj=jjj+str(int(nom))+", "</source>

 
<source>
jjj=jjj+"],"</source>

 
 
<source>
for nom in range(2,2*n-2,1):
   if nom % 2 == 0:
       kkk=kkk+str(int(nom))+", "
   else:
       kkk=kkk+str(-1+int(nom))+", "
kkk=kkk+"],"</source>

 
<source>
for nom in range(0,2*n-2,1):
   itens=itens+str((inten[nom]))+", "
itens=itens+"],"</source>

 
<source>
for nom in range(0,n-1,1):
   xxx=xxx+str((t[nom]))+", "
   xxx=xxx+str((t[nom]))+", "
xxx=xxx+"],"</source>

 
<source>
for nom in range(0,n-1,1):
   yyy=yyy+str((tsi[nom]))+", "
   yyy=yyy+str((tsi_2[nom]))+", "
yyy=yyy+"],"</source>

 
<source>
for nom in range(0,n-1,1):
   zzz=zzz+str((tco[nom]))+", "
   zzz=zzz+str((tco_2[nom]))+", "
zzz=zzz+"]}],"</source>

 
 
<source>
#print (itens)</source>

 
 
<source>
#print (iii)
#print (jjj)
#print (kkk)</source>

 
<source>
#print (xxx)
#print (yyy)
#print (zzz)</source>

 
 
<source>
fs=open("D:\\n_tre.txt","rb")
s=fs.read()
fs. close()</source>

 
<source>
fss=open("D:\ssss_tre.html","wb")
fss.write(s)</source>

 
<source>
fss.write((itens).encode('utf-8'))</source>

 
<source>
fss.write((iii).encode('utf-8'))
fss.write((jjj).encode('utf-8'))
fss.write((kkk).encode('utf-8'))</source>

 
<source>
fss.write((xxx).encode('utf-8'))
fss.write((yyy).encode('utf-8'))
fss.write((zzz).encode('utf-8'))</source>

 
 
<source>
fz=open("D:\\k_tre.txt","rb")
s=fz.read()
fz.close()</source>

 
 
<source>
fss.write(s)
fss. close()</source>

 
  



Еще картинка, тут меньше треугольников и специально оставлено как по умолчанию, перебираются последовательно номера точек для треугольников. Для равномерного цвета нужно через раз изменять направление обхода точек треугольника. 

Это похоже, как в формате STL при изменении направления обхода точек, изменяется яркость при просмотре. Изменяется вектор нормали к поверхности треугольника, а по вектору нормали рассчитывается освещение треугольника источником света. 

В Plotly есть полный комплект управления сценой и камерой, только осваивать нужно


Если точек немного, можно прямо с экрана скопировать вывод и заменить данные в файле html

Просмотр STL файлов
Сам STL файл может даже с форума.
Ниже немного картинок и код










Ниже код берет файлы STL, если слово vertex  начинается на шестой позиции. 
Можно работать с текстовыми файлами STL, размером 80 мегабайт.
Код формирует файл HTML, который можно включать на просмотр.
Начало и окончание файла должны быть в отдельных файлах. Эти файлы читаются и добавляются в выходной файл. 

Цвет каждого треугольника определяется нормалью треугольника.
Картинку конечно можно вращать и приближать

Насчет приближения картинки, немного неудобно, идет рывками, настраивать нужно. 
Есть аналогичная система K3D, вывод стабильней, но там цвета по умолчанию не такие яркие. Тоже настраивать нужно



<source>
import numpy as np
from numpy.linalg import norm</source>

 
<source>
def edv(tmp):
     dlina_tmp= norm(tmp, ord=2)
     ed_vektor=tmp/dlina_tmp
     return ed_vektor</source>

 
 
 
 
<source>
m=[]
t=[]</source>

 
<source>
#f1 = open("D:\\g.stl", "r")
f1 = open("D:\\Wt.stl", "r")
#f1 = open("D:\\B.stl", "r")</source>

 
<source>
f2=  open("D:\\Newstl.txt", "w")
for   line in f1.readlines():
      m.append(line)</source>

 
 
 
 
<source>
for   n123 in range(len(m)):
    line0=m[n123]</source>

 
 
<source>
                                       #   print "15",line
    line=line0.replace(",", ".")</source>

 
<source>
    if len(line)>18 and line[6] == "v":</source>

 
<source>
       line=line[6:]</source>

 
<source>
       if line!='\n':</source>

 
<source>
            t=line.split(" ")</source>

 
<source>
            if t[2].find("e")==8 or t[2].find("e")==9:
                 tmp=str(t[2])
                 tmp1=tmp.replace(",", ".")</source>

 
<source>
                 f2.write(str(tmp1))
            else:
                 f2.write(str(0))</source>

 
<source>
            f2.write("\t")</source>

 
<source>
            if t[3].find("e")==8 or t[3].find("e")==9:</source>

 
 
 
<source>
                 f2.write(str(t[3]))
            else:
                 f2.write(str(0))</source>

 
<source>
            f2.write("\t")</source>

 
<source>
            if t[4].find("e")==8 or t[4].find("e")==9 :</source>

 
<source>
                 f2.write(str(t[4]))</source>

 
<source>
            else:
                 f2.write(str(0))</source>

 
 
<source>
f1.close()
f2.close()</source>

 
 
<source>
         #222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
         #222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
         #222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
         #222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
m=[]
t=[]
f1 = open("D:\\Newstl.txt", "r")
f2 = open("D:\\Newstk.txt", "w")</source>

 
 
 
 
 
 
<source>
for   line in f1.readlines():
      m.append(line)</source>

 
 
 
<source>
import numpy as np
import math</source>

 
<source>
r=int((len(m))/3)</source>

 
<source>
xxx=""
yyy=""
zzz=""</source>

 
<source>
za=0</source>

 
 
<source>
inten=np.linspace(0, 22, r*3)</source>

 
<source>
for nn in range((r)):
    n=nn*3
    line0=m[n-1-2]
    line1=m[n+0-2]
    line2=m[n+1-2]
    n=n+3</source>

 
<source>
    t=line0.split("\t")
    x0=t[0]
    y0=t[1]
    z0=t[2]</source>

 
<source>
    t=line1.split("\t")
    x1=t[0]
    y1=t[1]
    z1=t[2]</source>

 
<source>
    t=line2.split("\t")
    x2=t[0]
    y2=t[1]
    z2=t[2]</source>

 
 
<source>
    cx0=float(x0)
    cy0=float(y0)
    cz0=float(z0)</source>

 
<source>
    cx1=float(x1)
    cy1=float(y1)
    cz1=float(z1)</source>

 
<source>
    cx2=float(x2)
    cy2=float(y2)
    cz2=float(z2)
    #print("____________r__________",nn,inten[(nn-1)*3],cx0)</source>

 
 
<source>
    v1=np.array(    [(cx1-cx0),(cy1-cy0),(cz1-cz0)]    )#        Первый вектор
    v2=np.array(    [(cx2-cx0),(cy2-cy0),(cz2-cz0)]    )#        Первый вектор
                                                                                                        ##            v3=np.array(    [(x3-x),(y3-y),(z3-z)]    )       Второй вектор
    napr=np.cross(v1,v2)
    napr=edv(napr)                                      #                                Сразу ставим единичную длину вектора</source>

 
<source>
    inten[(nn-1)*3]=napr[0]+napr[1]+napr[2]
    inten[(nn-1)*3+1]=napr[0]+napr[1]+napr[2]
    inten[(nn-1)*3+2]=napr[0]+napr[1]+napr[2]</source>

 
 
 
<source>
    xxx+=    (x0)+", "  +  (x1)+", "   +   (x2)+", "
    yyy+=    (y0)+", "     +(y1)+", "    +(y2)+", "
    zzz+=    (z0)+", "   +(z1)+", "      +(z2)+", "</source>

 
<source>
xxx+="],"
yyy+="],"
zzz+="]}],"</source>

 
 
<source>
i=np.arange(0,3*r-2,3, dtype=int)
j=np.arange(1,3*r-1,3, dtype=int)
k=np.arange(2,3*r,3, dtype=int)</source>

 
 
 
<source>
#itens=iii='"'+'intensity'+'"'+": ["
itens='"'+'intensity'+'"'+": ["</source>

 
 
<source>
iii='"'+'i'+'"'+": ["
jjj='"'+'j'+'"'+": ["
kkk='"'+'k'+'"'+": ["</source>

 
 
 
<source>
print ("244  r=",r)</source>

 
<source>
for nom in range(0,  3*r,  1):
   itens+=str((inten[nom]))+", "
itens=itens+"],"</source>

 
<source>
print ("253  r=",r)</source>

 
 
 
<source>
for nom in range(0,r,1):
   iii+=str(int(i[nom]))+", "
   jjj+=str(int(j[nom]))+", "
   kkk+=str(int(k[nom]))+", "</source>

 
<source>
print ("262  r=",r)</source>

 
 
 
<source>
iii+="],"
jjj+="],"
kkk+="],"</source>

 
 
<source>
xxx='"'+'x'+'"'+": ["+xxx
yyy='"'+'y'+'"'+": ["+yyy
zzz='"'+'z'+'"'+": ["+zzz</source>

 
<source>
fs=open("D:\\n_tre.txt","rb")
s=fs.read()
fs. close()</source>

 
<source>
fss=open("D:\ssss_tre.html","wb")
fss.write(s)</source>

 
<source>
fss.write((itens).encode('utf-8'))</source>

 
<source>
fss.write((iii).encode('utf-8'))
fss.write((jjj).encode('utf-8'))
fss.write((kkk).encode('utf-8'))</source>

 
<source>
fss.write((xxx).encode('utf-8'))
fss.write((yyy).encode('utf-8'))
fss.write((zzz).encode('utf-8'))</source>

 
 
<source>
fz=open("D:\\k_tre.txt","rb")
s=fz.read()
fz.close()</source>

 
 
<source>
fss.write(s)
fss. close()</source>

 
 
 
<source>
f1.close()
f2.close()</source>