Open noooway opened 5 years ago
Что есть:
В расчетной области иногда нужно задавать геометрические объекты. Они могут либо определять форму источника частиц, либо форму электродов, от которых нужно считать поле.
В перспективе хочется импортировать геометрические объекты из CAD-систем. Например, сделать поддержку STL или STEP форматов. Но для простых тестов полезно иметь минимальную поддержку геометрии без внешних зависимостей.
Т.е. интерфейс мог бы выглядеть как-то так (см. https://github.com/epicf/ef_python/blob/geometric-primitives/GeometricPrimitives.py ):
class GeometricPrimitive:
def __init__(self):
self.expression = None
@classmethod
def init_primitive_from_string(cls, expression):
pass
@classmethod
def init_primitive_from_hdf5(cls, h5field):
pass
def check_if_point_inside(self, point):
pass
def generate_random_point_uniform(self, random_in_range_function):
pass
def write_hdf5_attributes(self, h5field):
pass
Что можно сделать:
Более-менее несложная вещь, которую можно попробовать реализовать - это конструктивная сплошная геометрия https://en.wikipedia.org/wiki/Constructive_solid_geometry . В ней определяется несколько трехмерных примитивов - цилиндр, сфера, куб, конус и др. , стандартные булевы операции - объединение, вычитание, пересечение и стандартные трансформации - сдвиг, масштабирование, вращение. Из них собираются объекты.
Получается что-то типа:
(difference (cylinder r=5, l=10) (cylinder r=3, l=10))
или
tube = Cylinder(r=5, l=10) - Cylinder(r=3, l=10)
Такой подход реализован в OpenSCAD https://en.wikipedia.org/wiki/OpenSCAD .
difference()
{
cube([20,20,20]); // a 20 mm cube
translate([10,10,-1]) // start 1 mm below the surface
cylinder(r=5,h=20+1+1); // and go 1 mm above
}
Также есть питон-модуль https://github.com/SolidCode/SolidPython , который позволяет использовать питоновский синтаксис для описание объектов и генерировать OpenSCAD-фаилы.
from solid import *
from solid.utils import *
d = cube(5) + right(5)(sphere(5)) - cylinder(r=2, h=6)
Думаю, что имело бы смысл реализовать в программе что-то похожее. Тогда можно будет писать в конфиге такие вещи:
[InnerRegion.tube]
potential = 0.0
geometry = (difference (cylinder r=5, l=10) (cylinder r=3, l=10))
Необходимость инициализировать объекты из текстовой строки создает проблемы - нужно писать парсер для строк.
Можно использовать S-выражения:
(difference (cylinder r=5, l=10) (cylinder r=3, l=10))
Они удачно подходят для такой задачи. Готовые парсеры можно найти в https://rosettacode.org/wiki/S-Expressions .
Можно использовать подход SolidPython и использовать парсер и синтаксис питона, т.е. конструкции типа
tube = Cylinder(r=5, l=10) - Cylinder(r=3, l=10)
Для разбора математических формул в SimpleEval https://github.com/epicf/ef_python/blob/geometric-primitives/libs/simpleeval/simpleeval.py уже используется AST https://docs.python.org/3/library/ast.html . Думаю, на основе AST можно сделать еще один нужный парсер.
Можно попытаться найти парсер OpenSCAD фаилов на питоне.
Возможно, есть еще какие-то варианты.
Также имеет смысл сделать визуализацию геометрии. Можно сделать либо экспорт в OpenSCAD формат, либо посмотреть визуализацию в jupyter-модуле https://github.com/epicf/ef_python/blob/master/ef/config/visualizer.py , либо в https://github.com/nickc92/ViewSCAD .
Можно попробовать использовать json в качестве формата и json-модуль в качестве парсера. После считывания строки в словарь разбор словаря уже будет проще.
Еще нашлось несколько библиотек на питоне:
Еще нашлись любопытные альтернативы OpenSCADу:
Currently there is some code duplication between InnerRegions and ParticleSources concerning their geometric shape. It seems natural to define separate classes for geometric primitives and utilize them.
The work has been started in https://github.com/epicf/ef_python/tree/geometric-primitives branch.
For each primitive it is necessary to provide at least two methods: a way to check if a point with given coordinates is inside this primitive (to remove particles after collision) and a way to generate a point inside it (for sources).
Besides, annoying problem is to read primitive definitions from config. There is no natural support for subsections in INI-files so it is necessary to write geometric primitives as strings and then parse those string in class constructors. It has been implemented (though not tested yet), but probably there is a better solution.
Current status: It is necessary to test initialization of classes from text string. And it is necessary to replace current geometry-related code in inner regions and sources with this new classes. Then it would be necessary to update and test examples.