MoI discussion forum
MoI discussion forum

Full Version: MoI embedded inside CPython 3.91?

Show messages:  1-15  16-35  36-44

From: bemfarmer
20 Feb 2021   [#16] In reply to [#15]
Success, (pending confirmation of surface created), at creating new surface point network, .csv, and importing the network of curve points back in to MoI interpcurve. MoI>Network>gSurface looks nice. Now to clean up the code...and get the project all together.
There are so many setting possibilities--myriad...
Sill need to apply MoI symmetry and mirror operations...
This python script runs in Python 3.9.1.
Input gDomain.CSV is in Desktop. Output gPatch.CSV is now also in the Desktop.
Plan on doing a denser input mesh of curves...

code:
#gNetP1.py, from gDomain.csv, create gNetP1.csv

import numpy as np
import pandas as pd
import csv
from mpmath import *
mp.dps = 25 #; mp.pretty = True
aScale = 1
#K = 1.68575035481259604287120365779
K = ellipk(0.25)
#Kp = 2.1565156474996432354386749988
Kp = ellipk(0.75)
Kpp = (K*K + Kp*Kp)
#theta = 0.6634829705114348080575689, Bonnet angle, radians, ~38.0147739891°
theta = acot(Kp/K)
kappa = aScale*mp.sqrt(Kpp)/(K*Kp) # normalization constant
EiTheta = complex(mp.cos(theta),mp.sin(theta))
sqrt2 = mp.sqrt(2)
twoSqrt2 = 2 * sqrt2
mod97 = (97+0.24484) - 56 * mp.sqrt(3)
zeta = 1/sqrt2
eta = aScale/4
# Import csv coordinate values and curveIndex
# MODIFY orcha to <username>, and use your gDomain.csv:
csvInPath = r"C:\Users\orcha\OneDrive\Desktop\gDomain.csv"
columns = ['xCol', 'yCol', 'zCol', 'cIndex'] #names of columns
dtypes = {'xCol': np.float64, 'yCol': np.float64, 'zCol': np.float64, 'cIndex': np.int64} #dictionary
gDomain_df = pd.read_csv(csvInPath, header=None, names=columns, dtype=dtypes)

# Setup output gNetP1.csv.
with open('C:\\Users\\orcha\\OneDrive\\Desktop\\gNetP1.csv', "w", newline="" ) as f:
  writer = csv.writer(f)
  for i in range(0, len(gDomain_df)):
    x = gDomain_df.at[i, 'xCol']
    y = gDomain_df.at[i, 'yCol']
    cIdx = gDomain_df.at[i, 'cIndex']
    w = complex(x, y)
    ww = w * w
    wwww = ww * ww
    ww4 =  ww * 4   
    numer1 = w * twoSqrt2
    denom3 = wwww + 1			
    denom1 = mp.sqrt(denom3 + ww4)
    quotientX = (numer1 / denom1)
    quotientY = (((-1)*numer1) / denom1)
    quotientZ = (ww4 / denom3)    
    as1 = asin(quotientX)
    as2 = asin(quotientY)
    as3 = asin(quotientZ)
    myf1 = (ellipf(as1, 0.25))/twoSqrt2
    myf2 = (ellipf(as2, 0.75))/twoSqrt2
    myf3 = (ellipf(as3, mod97))/4
    x1 = kappa*((EiTheta * myf1).real)
    y1 = kappa*((EiTheta * myf2).imag)
    z1 = kappa*((EiTheta * myf3).real)   
    X = float(nstr((-zeta*x1 - zeta*y1), 17, min_fixed=0, max_fixed=0))
    Y = float(nstr((-zeta*x1 + zeta*y1 + 2*eta), 17, min_fixed=0, max_fixed=0))
    Z = float(nstr((z1 + 3*eta), 17, min_fixed=0, max_fixed=0))
    writer.writerow([X, Y, Z, cIdx])



- Brian
Revised 3/2/2021, uses Desktop for location of files.
From: bemfarmer
20 Feb 2021   [#17] In reply to [#16]
# gPatch.py is a Python program to create a gyroid surface point network, from a CSV file from MoI.

# Data flow:
# wDomainG.3dm surface curve network is created in MoI.
# wDomainG.3dm > gDomain.csv, (point coordinates), via MoI SavePointNetwork script.
# gDomain.csv > gDomain_df, via gPatch.py program, using Python pandas.
# gDomain_df > gPatch.csv, via gPatch.py program.
# gPatch.csv > gPatchNetwork.3dm, via MoI ImportPointNetwork script, to form a curve network.
# gPatchNetwork.3dm > gPatchSurface > gyroid, with MoI.

# Data structures:

# gDomain.csv, a TEXT file with one [x, y, z, curveIndex] row per point, with no Header row, and no rowIndex. (All elements of any csv file are text.) (The delimiter is a comma.)
# For this particular project, the z values are all zero, and are not needed, and also the x,y points represent the complex number (x + yj).

# gDomain_df, a pandas data frame. Header is (x, y, z, cIndex), rowIndex is a column of integers. x, y, and z are float64. cIndex is int64. (cIndex denotes which curve a point is on.)

# The gPatch.py program calculates the (new) X, Y, and Z, float64 coordinate values.
# gPatch.csv, a TEXT file with one [X, Y, Z, curveIndex] row per point, no Header row, no rowIndex.
# The imported text numbers become Javascript numbers, which are the same as numpy float64.

# Overview of gPatch.py program:
# Ignoring z, each x, y, z, and cIndex element in gDomain_df is processed in turn. Coordinate (x,y) is converted into a complex number "w". Certain complex number math equations are applied to "w" to yield real number values for new surface coordinates (X,Y,Z), for each cIndex. Each [X, Y, Z, cIndex] list is saved to a row of gPatch.csv.

# MoI script ImportPointNetwork.js is used to import the new surface point coordinates, and iCrv, from the gPatch.csv text file. The ImportPointNetwork option to create Interpcurves should be used. The new curves form a network of curves. MoI Network command should then be used to create the fundamental gPatchSurface. Next various MoI commands Mirror and Rotate can be used to create the GYROID UNIT, and then the cubical gyroid unit cell. Join or Boolean...

# Superb links using Iris.csv data, a 1937 flower database:
# https://datascienceparichay.com/article/read-csv-files-using-pandas-with-examples/
# https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html
# https://songthamtung.medium.com/pandas-csv-cheatsheet-f88abecbe289
From: bemfarmer
20 Feb 2021   [#18] In reply to [#17]
Credits:
The complex mathematics for the Python script is based upon three papers by Paul J.F. Gandy, and Jacek Klinowski:

"Exact computation of the triply periodic G ('Gyroid') minimal surface," (& D & P), available at:
https://dokumen.tips/download/link/exact-computation-of-the-triply-periodic-g-gyroid-minimal-surface

https://www.researchgate.net/publication/234138905_Exact_computation_of_the_triply_periodic_D_'diamond'_minimal_surface

https://www.researchgate.net/publication/223147236_Exact_computation_of_the_triply_periodic_Schwarz_P_minimal_surface

(The papers are very similar, and complement each other, but do have some inconsistency errors/ typo's, and some elements that are not entirely understood.)

Symmetry operations will be done in MoI.
Next, the input domains for the D_diamond and Schwarz_P surface will be processed.

- Brian

Low density .3dm of the patch attached. Just perform MoI Network on it...

It has been a few months since I studied the symmetry (mirror) planes, and rotational axi...must review.
From: bemfarmer
21 Feb 2021   [#19] In reply to [#18]
Corrected error in code.
Not at all clear where the symmetry planes and rotation axi are, so:
Running the script 12 times, with zeta and eta equations modified, produces all 12 patches.
Should modify the script to run once, and write all 12 csv files.
Or figure out symmetry and rotation, maybe in a node...

Increased density of input domain to 41 curves, 100 points per curve.
Running one patch, 4100 points, only takes a few seconds.

- Brian

Eventually will try to open MoI4 from Python, and pass output 3D CSV and run ImportPointNetwork???
From: bemfarmer
21 Feb 2021   [#20] In reply to [#19]
Over a 1cm scale:
12 patches almost fit in a unit cube, but not quite.
Pairs of patches, e.g. netP1 and netP2 join up well, with horn to horn distance of 1cm, but the two vertices are off from the corners of the unit cube by ~0.0167468cm.
After line_line these two vertices, the 3rd vertex is about .023733cm short of the center of the cube.
Patch(P1+P2) does not quite adjoin patch(P3+p4), etc.
Will check number of decimals of point coordinates tomorrow.
- Brian
From: bemfarmer
24 Feb 2021   [#21] In reply to [#20]
The equations in the gyroid paper involve .real and .imag extraction of real number from complex number.
The term e(power(i*theta) = cos(theta) + i*sin(theta) also must have .real and .imag applied at some point.
The paper ignores this, or has typo omitting when to apply this. I am trying some permutations...

Maybe doing the D and P surfaces will help with understanding. Cos(0) = 1, and i*Sin(PI/2) = i, so only a sign change is possible.
- Brian
From: bemfarmer
27 Feb 2021   [#22]
I have been over and over the equations, and also have made python code for the P and D minimal surfaces. None of the wavy triangular-ish surface nets is quite right. The numbers are mostly complex. I now suspect that the mpmath asin or ellipf functions are faulty???
Maybe it is "branch cuts"?
May try mathematica...
- Brian
From: bemfarmer
28 Feb 2021   [#23]
Very promising:
https://pypi.org/project/wolframclient/
https://reference.wolfram.com/language/WolframClientForPython/
Would still need to rent or buy mathematica...
- Brian
From: bemfarmer
2 Mar 2021   [#24]
The Gandy/Klinowski paper appears to have an incorrect formula for the Z coordinate, or my Python program was doing something wrong.
Correcting the modulus squared to (97+0.24484) - 56 * mp.sqrt(3) seems to correct the problem, and all of the 12 patches meet up "perfectly".

Attached are the 12 python scripts for producing the 12 patches of a gyroid boundary surface.
The 12 scripts are the same, except for the ending 3 lines defining X, Y, and Z.
Input is gDomain.csv, created in MoI with SavePointNetwork script
Outputs are gNetP1.csv, gNetP2.csv, ...gNetP12.csv, placed in Desktop. (Adjust paths)
The 12 gNet__.csv files are input to a network of 22 curves in MoI, with the ImportPointNetwork script, run 12 times.
The 12 networks quickly individually Network to 12 surfaces.
The 12 surfaces quickly join to the gyroid boundary surface.

Next to be done is described in Table 2 of the paper, some mirrors and translations.
Eight boundary surfaces make up a triply periodic face-centered cubic unit cell of the G surface. This should be easy to accomplish in MoI.

- Brian

Attachments:
GyroidMarch2_07.7z
gyroidPatch3_2_2021.zip


From: bemfarmer
2 Mar 2021   [#25]
Bounding Cell of the Schwarz Diamond TPMS.
This consists of 6 patches from python program dPatch6, which form a "Pinwheel".
A cplane was placed at the center of the Pinwheel, with the Z circle axis indicator moved to the point shown, at the midpoint of the front upper cube edge.
A mirror was done from said center.

It is hard to grasp all of the mirrors and rotations, etc...

Yet to be done:
4 bounding cells make an octant (1/8).
8 octants make a face centered unit cell of the D surface.

The pipeDomain file is the MoI created initial .csv file, used for both D and P surfaces. Created from a planar .3dm grid network, half of the gDomain grid network.
The 6 dPatch python scripts turn the pipeDomain.csv into 6 point network .csv files for ImportPointNetwork script back into MoI network of curves.

- Brian

Attachments:
dPatchPythonScriptsAndPipeDomain.zip
SchwarzD_March01BoundingCell_6patch_times2_05.zip


From: bemfarmer
3 Mar 2021   [#26]
The boundary cell of the Schwarz-P minimal surface is made up of 6 patches from Python.
The pair of parch surfaces from net Patch pair (P1 plus P2), are revolved along line from pinwheel center to a cube edge middle.
The new pair of surfaces is then axis rotated 120 and -120 degrees, with line from M1 through M7, centered on pinwheel centerpoint.

Not done yet:
It is easy to see how 8 boundary patches create the 6 holed unit cell of the P surface.

- Brian

Attachments:
P_D_PatchFeb2021.zip
SchwarzP_BoundaryCell.7z


From: bemfarmer
9 Mar 2021   [#27]
Forming the Gyroid unit cell from 8 of the 12 patch boundary cells:

Table 2 of the Gyroid paper of Gandy & Klinowski can be understood in terms of 4X4 homogeneous transformation matrices, and also in terms of MoI mirror and move commands acting upon boundary patch surface O1 which consists of 12 basic patches. Surface O1 is represented by all of the points (xprime, yprime, zprime) on its surface. Dropping the prime from the name, one generic point (x, y, z, 1) written in homogeneous coordinates as a column vector, {(x, y, z, 1)T, transposed}, is sufficient to create all of the matrices and corresponding Mirrors, (reflections), and Moves (translations), to build the complete unit cell of a Gyroid.

The move distance unit 'eta' is 1, and the distances moved are 0, 1, -1, or 2 units, along the various axes. The final cube is 2 units on a side.

O1 is located in quadrant 1, with the cube enclosing it aligned with the 3 positive xyz-axes, with lower left corner at the origin.

O2 corresponds to [(-x+2), (-y+1), z, 1]

The corresponding composite matrix, cM01, is: (remember zero indexing.)
row 0: -1 0 0 2
row 1: 0 -1 0 1
row 2: 0 0 1 0
row 3: 0 0 0 1

In Top View:
In row0, the "-1" (and position) denotes mirror in yz plane. For this mirror, select the origin for the 1st point, and select another point, on the y axis, for the 2nd point. The "2" (and position) denotes the Move in the +x direction, of 2 units.

Still in Top View:
In row1, the "-1" (and position) denotes mirror in the xz plane. For this mirror, select the origin for the 1st point, and select another point, on the x axis, for the 2nd point. The "1" (and position) denotes the Move in the +y direction, of 1 unit.

The composite matrix cM01 can be broken down into 2 matrices.
O2 = cM01 * O1 = moveM * mirror_yzM * mirror_xzM * O1.
The correspodiing MoI commands applied to surface O1 are:
mirror_xz, then to result: mirror_yz, then to result: move (2, 1, 0) units.
In this case, the three operations can be applied in any order (???)
(Note that for the Schwarz D surface, (some of) the matrices are rotation, reflection, then move, where order DOES make a difference.)

With practice, certain key row column locations in the 4X4 matrices are recognized for the mirror, and move results. Schwarz D rotations are a bit harder...

Next up is to see if the nodeeditor Mirror will work properly, or not.
Then build a nodeeditor program with Frames, macros for various mirrors, and moves, etc., for G, D, and P surfaces.
Also to do, decompose the 12 steps of Table 1 for the Gyroid fundamental patch, into matrices and nodeeditor program.

For rotations, with a D boundary patch aligned with xyz-axes, the rotations are PI/2, so the cosine matrix entries are zero, and the sine entries are +1. And reflections are xy, yz, and/or xz planes.

- Brian
From: bemfarmer
10 Mar 2021   [#28]
The Gyroid_fcc_UnitCell node builds the face-centered-cubic unit cell of a Gyroid.
The node recapitulates Table 2 of the paper.

The Input is the 12 member Gyroid boundary surface, with default color style "default".
(GyroidMarch2.3dm file.)

The input could alternatively be said surface, offset a small amount, to one side, or both sides.
The 12 individual network curve fundamental gyroid patches can be easily individually networked and offset. (The whole boundary does not offset, but the individual fundamental offsets can be joined.)

Color styles were used for input "Get By Style", because the individual outputs can be set to colors other than the input style. Get By Name could be used, but THERE IS NO OBJECT NAME CHANGE node in nodeeditor AFAIK, so the source fundamental patch is not isolated.

- Brian

Next up is to make a node for Table 1 of the paper, 1 fundamental patch to 12 patch Boundary gyroid patch. This would only need one Python generated basic fundamental patch 1, not 12 Python programs.

Schward D and P tables are yet to be turned into nodes.

Attachments:
Gyroid_fcc_UnitCell.zip


From: bemfarmer
12 Mar 2021   [#29]
For Table 1, the beginning fundamental patch will be Patch0, rather than Patch1. The python code will use the x,y,z point outputs, rather than the X,Y,Z point outputs.
(Note that python X = the papers xprime, etc.)
Application of zeta = 1/sqrt(2), which is sine or cosine of 45 degrees = PI/4, and move of eta = n*(1/4) will be done by gyroidTable1.nod program (still being created).
P0 ===> P1
P0 ===> P2
P0 ===> P3, etc.
It seems that a mirror in the Plane_(Y=Z), X, will be needed for P3. Note that this is NOT the YZ plane, rather it is the plane which includes the x-axis, and is 45 degrees between the Y and Z axes.
A Macro, believed to be correct, partly by trial and error, is attached.

- Brian

Attachments:
Macro_Plane(Y_equals_Z)X.zip


From: bemfarmer
13 Mar 2021   [#30]
gPatchP0_01.3dm is a new network of curves for fundamental gyroid patch P0, via Python math and .css files, without zeta rotation of 45 degrees, and without eta move of n/4. (zeta and eta, greek letters, are defined in Table 1. The typesetter got zeta mixed up with another greek letter.)

GyroidBoundaryFrom_gPatchP0_02_3dm.7z is the nodeeditor program which uses P0 to produce P1 and P2, in MoI, with Table 1 Transformations. (rotate, mirror, move). The node permits quick variations in the +/- rotation degrees, the mirror plane(s), and the move amounts.
Nodes for P3...P12 have not yet been done. The sign of both 45 degree rotations had to be reversed from the angle figured out.

MatrixMultiply4.zip is an Excel 365 program to multipy matrices with number entries, to assist in decomposing each composite matrix for each line entry in Table 1.

Each composite matrix is created manually from the [x, y, z,1] (transposed) vector.
A symbolic matrix multiplier in Excel would be helpful...

- Brian

ps The node program has a macro for the XY plane/frame for mirror can be exported, and a copy placed in the macro folder of nodeeditor.
gPatchP0 network can be networked to a surface. The surface can be offset a little, if desired. The net, or the surface(s) can be input to the node program to yield P1 and P2, etc.

EDIT: Updated .node program and Excel 365 programs are in post 31.

Attachments:
gPatchP0_01.7z
GyroidBoundaryFrom_gPatchP0_02_3dm.7z
MatrixMultiply4.7z


From: bemfarmer
14 Mar 2021   [#31]
Patch P3 and P4 successfully created from P0, with nodeeditor program.
So far, each successive patch has used an additional MoI command / Matrix.

Excel 365 matrix math with numbers is great.
Doing matrix "symbolic" math, like .707*z would require some involved programming... Web searches are not much help.

Decomposing a matrix composed of multiple unknown matrices for revolve and mirror is not so easy, and can have multiple, different, correct solutions.
Some mirror mirror ... operations can be done with rotations & ? ... somehow.
Web search results are too simple or too complicated...Some are for elementary school, and some for mathematicians.

Only 8 more patches to figure out...

Edit: Different symmetry operations to create Patch P3 and P4 were created. See post 33.

Attachments:
MatrixMultiply1234.7z


From: bemfarmer
17 Mar 2021   [#32] In reply to [#31]
After much study and failed transformations, Table 1 is finally turned into a node, to produce the gyroid boundary patch from pre-fundamental patch P0 to P1.
P1 transforms into P2, and the remaining 10 patches. Must write it up. I think clockwise 90 degree rotations and ccw 90 degree rotations are inconsistant with respect to x, y, and z axes and +/- 90 degrees?
It also helps to think in terms of world axes.

- Brian
From: bemfarmer
25 Mar 2021   [#33]
A concise node program to create the 12 patch gyroid boundary patch is complete. Use of some Macros makes the wiring look much better.
The Inversion center permits half of the 12 patches to be simply inversions of the other 6 patches. A simple inversion macro is included in one of the macros, which can be added to the symmetry operations repertoire.
The initial patch P0, created in Python is attached. Either the netP0, or the surfaceP0 may be used, or both, as input to the node program. The surface P0 could be extruded a bit, if desired.
When a rotation axis is pointed at the observer, for a Clockwise rotation of 90 degrees, use +90 for the Euler angle in the rotate node. This is contrary to the right hand rule and contrary to the convention that CCW rotation is positive.
The symmetry operations of Table 1 are complete. It took a long time to figure out how the symmetry operations work. The symmetry operations apply to the MoI World axes. To create say P3 from P1, notice that xprime equation of P1 needs to be negated with an initial mirror with yz plane. Then rotate about MoI x axis clockwise, by +90 degrees. This shifts (rotates) zPrime equations of P1 to yPrime equations of P3. Then rotate about MoI y axis by +90 degrees clockwise. This shifts (rotates) the old yPrime equations of P1 to the xPrime equations of P3, and the old xPrime equations of P1 to the zPrime equations of P3.
The last step is a simple move (translation) of n*eta = n*(1/4). In summary, it seems to be a lot easier to "rotate" the equations of table 1 from P1 to P3 and P11, and invert to P5, P7, and P9, and similarly from P2 to P4 and P12, and invert to P6, P8, and P10, rather than try to decompose matrices.
The new SetName node belongs in the nodeeditor extensions folder.

- Brian

Attachments:
GyroidPatch_P0_to_BoundaryPatch12.zip
GyroidPreFundamentalPatchP0.7z


From: bemfarmer
27 Mar 2021   [#34]
I have been reading forum posts about shellExecute, and reading lots of google searches, with very limited results, and poor understanding.

# In Windows 10, the line of code below, following these comments, will open a python window from the MoI command box.
# Note that python 3.9.2 is already installed in the path shown.
# Note that it is necessary that \ are doubled in the path, and path must be correct.
# In MoI4, press Tab, and paste the line of code into the MoI command box and press enter.
# Code:
moi.filesystem.shellExecute( 'C:\\Users\\orcha\\AppData\\Local\\Programs\\Python\\Python39\\python.exe' )

# This Code works too:
moi.filesystem.shellExecute( 'C:\\Users\\orcha\\AppData\\Local\\Programs\\Python\\Python39\\python' )

# In Windows 10, the line of code below, following these comments, will open Rhino7 from the MoI command box.
# Note that Rhino7 is already installed in the path shown.
# Note that it is necessary that \ are doubled in the path, and path must be correct.
# In MoI4, press Tab, and paste the line of code into the MoI command box.
# Code:
moi.filesystem.shellExecute( "C:\\Program Files\\Rhino 7\\System\\Rhino.exe" )

Michaels Example code works:
var res = moi.filesystem.shellExecute( 'cmd /c dir c:\\', '', true );
if ( res.output ) moi.ui.alert( res.output );

So far, I have been unable to pass any python code or arguments, nor will the following code do anything:
var res = moi.filesystem.shellExecute( 'C:\\Users\\orcha\\AppData\\Local\\Programs\\Python\\Python39\\python sys.stdout.write("I am a test")', '', true );
if ( res.output ) moi.ui.alert( res.output );

I guess Windows stdout is different from python stdout?

(Still reading google searches...)

- Brian
From: Michael Gibson
27 Mar 2021   [#35] In reply to [#34]
Hi Brian, does it behave any better if you pass the parameters as the second argument to moi.filesystem.shellExecute() ?

Something like this:

var res = moi.filesystem.shellExecute( 'C:\\Users\\orcha\\AppData\\Local\\Programs\\Python\\Python39\\python', 'sys.stdout.write("I am a test")', true );
if ( res.output ) moi.ui.alert( res.output );

- Michael

Show messages:  1-15  16-35  36-44