MoI discussion forum
MoI discussion forum

Full Version: MoI embedded inside CPython 3.91?

Show messages:  1-7  8-27  28-44

From: bemfarmer
3 Feb 2021   [#8]
This morning, I re-read Dave Morrill's posts about External Scripting Interface for MoI, written in Python (Traits/Facets), creating Javascript code to perform MoI commands.

It seems that Nodeeditor performs these tasks, without Python.

Now all that is needed is to write part of Nodeeditor in Python ??? Somehow?
Allowing Nodeeditor to access the Python cMath/ NumPy and sciPy functions.

- Brian
From: bemfarmer
3 Feb 2021   [#9]
Using Nodeeditor and Python to process points from MoI

The purpose of these outline notes is to apply Python complex number math functions to the x and y coordinates of 2d, or 3d, points in the MoI top view. In this case, the z coordinates of the points are either ignored, or zero, but may be used in some other situation. The z value is included for future flexibility. The x values are real, and the y values are real, but are treated as imaginary. Complex number z = x + i*y.

Initial MoI geometry is a network, IntegrationDomain, of a score or so planar curves in the xy plane. Nodeeditor will be used. A new node, which incorporates modified LineWeb style code, will be used to array numerous points on each successive curve. A new node, SavePoint4.js, modeled on the MoI SavePoint script, will export the point coordinates to a CSV1 style text file, with a certain delimiter. The CSV1 file will have a typical CSV format. Each line is a list of 3 coordinates, and curveIndex, for one point. Format: x, y, z, cIdx where x, y, and z are real numbers, and cIdx is an integer which indexes each parent curve, and the new curves to be created later.

Next, in a separate Python program, ComplexTransformMap.py, will import the CSV1 file. Complex number functions in cMath, NumPy, and SciPy will be used.
For each curve index, the x and y values will be converted to the complex number class, essentially an (x, y) pair representing the complex number x + i*y. The appropriate complex number math will be applied to each (x, y) to create a new 3d point, (X, Y, Z, cIdx). Python will then Save (output) all of the (X, Y, Z, cIdx) points to a new CSV2 file, PatchPointNetwork, consisting of the same number of network curves to be created from the new points.

Next, in a separate node program, PatchProcessor, will import CSV2, with node CSV_File4, based upon Karstens Import/CSV_File node, converting the (X, Y, Z) points with matching curve index, into a new curve. All of the new curves will be a new network of curves, PatchNetwork. MoI Network command will be applied, to generate a surface Patch. Then Mirror and Symmetry operations are applied to the surface Patch, to generate the final result.

The hardest part is learning enough Python to write a short Python program.
Google search of "python csv import" yields lots of hits, as does "python csv export".

- Brian
From: bemfarmer
7 Feb 2021   [#10] In reply to [#9]
_SavePointNetwork.js script, by Brian E. McMillin, February 2021

This script outputs a CSV style text file containing four fields,
[x, y, z, curveIndex], with "comma" or other delimiter. (No []).
Each row contains the point coordinates for one point on the associated indexed parent curve.
The parent curve entries are also in order.
The values of x, y, and z are real numbers, and iCrv = crvIndex is a positive integer, which could include 0.

Input to the _SavePointNetwork script is a set of curves.
The curves could be in a network representing a surface.
For each sequential curve, a startpoint is arrayed on the curve,
to create numPts number of points, in order, for that curve.

Credits:
Michael's scripts Lineweb, SavePointFile (non-ActiveX version). (Grafted together)

Several hours were spent on an incomplete node version.
This script turned out to be fairly easy and simple, after much effort extracting and comparing parts of the credit scripts.

Yet to be done:
A companion script would be ImportPointNetwork, which does the reverse.
ImportPointFile + Karstens Import/ CSV_File node.

Testing has been very limited...

Python import CSV, Bonnet transformation, and export CSV.

Also attached is the network of curves which is the integration domain.
(This networks represents the Complex number plane, and the points complex numbers.)
The network density could be increased or decreased.
It is associated with bonnet angle in radians of 0.66348297051143481, which is an angle of about 38.0147...~ degrees.

- Brian

To utilize the script, place the .js and .htm files in the command folder of MoI. In my case this is the "additional non-stock script" command folder in AppData.
The _ prefix can be removed, or left in for usage with CustomUI.

Attachments:
SavePointNetwork.zip
wDomain_G.zip


From: bemfarmer
8 Feb 2021   [#11] In reply to [#10]
The script could be modified to not output the z coordinate.
- Brian
From: bemfarmer
10 Feb 2021   [#12]
_ImportPointNetwork.js script, by Brian E. McMillin, February 2021

This script inputs a CSV style text file containing four fields,
[x, y, z, curveIndex], with "comma" or other delimiter.
The [] are NOT used in the file.

A three fields version for 2D points, [x, y, curveIndex], was NOT implemented,
due to possible confusion with CSV files without curveIndex.
curveIndex is a positive integer, which could include 0.
Each set of points has a different curveIndex = iCrv.

If the option to form Polyline(s) or ControlPts curve(s) or InterpcurvePts curve(s) is chosen,
then a different Curve is formed for each different iCrv.

Each row contains the point coordinates for one point, plus the curve index.
Rows for a set of points (with same curve index) need to be together, in order.
Companion script is _SavePointNetwork, which could be used to make a quick test file. One 3 curve test file is included in the zip.
It is anticipated that _SavePointNetwork is used to send the point CSV to a third party program, for processing.
The third party program would then export new X,Y,Z,curveIndex points, to be Imported back into MoI, as one of the 3 curve types.
Points could also be the result, but would be a cloud.

Credits:
Michael's scrip ImportPointFile was modified to create different curves.

The script has received only limited testing.
I had a lot of trouble getting the script to work, due to poor programming skills.
The last for loop had to have = instead of <, for some unknown reason, to plot the first point set.
.shift() was used instead of .pop().

No telling what the results would be for a weirdly formatted CSV file...

- Brian

Attachments:
_ImportPointNetwork.zip


From: bemfarmer
13 Feb 2021   [#13] In reply to [#12]
A python program typed into Notepad++ can be run from the Notepad++ screen, with the run key. (Windows 10).
Windows environmental variable (proper path) has to be set up, and the proper command entered into the run window of Notepad++.
The youtube video https://youtu.be/yxTbSTrCn6I explains the requirements, after watching several times.
My notepad++ run entry is C:\XXXX\orcha\AppData\Local\Programs\Python\Python39\python.exe -i "$(FULL_CURRENT_PATH)"
Be sure to include a space before, and also after the -i.
The XXXXX entry is to be replaced with the users "username".
I'll post my python csv import (from MoI savepointnetwork script) and also python csv export (to MoI importpointnetwork script) when completed.
Rudimentary Python scripts do not seem too hard. The worst thing is there are numerous alternate ways to handle csv import, and 3 alternate data structures,
list or array or nparray.

- Brian
From: bemfarmer
14 Feb 2021   [#14]
Finally got Python paths straightened out, and installed numpy, scipy, and pandas with pip. It is fairly easy, but everything has to be just right, or nothing works.
There are too many permutations and alternatives...

After many challenges, finally was able to Read a CSV text file of point coordinates with Pandas, into a pandas DataFrame(), a type of super Deluxe "array" in Python.
It only took 3 lines of code, but I searched a couple of hundred example lines of code...

A superb link: https://datascienceparichay.com/article/read-csv-files-using-pandas-with-examples/

The math should not be too hard.
Re save to X,Y,Z,curveindex should be fairly easy.

- Brian
From: bemfarmer
17 Feb 2021   [#15] In reply to [#14]
After an ordeal of a few days of google web surfing scores of websites, and study of Python and Pandas, I was finally able to get a MoI SavePointNetwork.csv imported into Python 3.9.1.
A grand total of 4 lines of code! So many permutations do not work, and there have been version changes also.

The path will need to be modified to the individuals folder structure. Change orcha to your username. Remove OneDrive folder from path, if it is not used.
Place the gDomain.csv file created from MoI into your Desktop folder. The r needs to stay. The plural and singular names must stay the same. # HashTags are comment lines, like Javascript //
Open Python 3.9.1 from Windows 10 start menu.
Paste in the above code, and hit return, to see the pandas Data Frame, which looks like an excel spreadsheet.
Hit return again, to see the data types of the numbers.
The .csv numbers are text strings.
The Data Frame point coordinates are np.float64, and the cIndex is np.int64. (Javascript numbers are also all 64 bit.)
The row index column on the left, and the column names are not essential, but will be used to access the coordinates.

Attached is a truncated gDomain.csv for testing purposes. It has 10 points for each of 3 parent MoI curves.

- Brian

(Running python code in Notepad++ worked in a super simple case, but does not work in general.)

Attachments:
gDomain.zip


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

Show messages:  1-7  8-27  28-44