Я программирую на C ++ 3d-сцену, в которой деревья можно «выращивать» в любой точке и в любом направлении. Я нахожу, что деревья / планеты L-систем выглядят очень хорошо, но я не могу найти в Google какую-либо функцию или библиотеку, которые могут позволить мне передать координату точки, вектор направления и некоторые другие параметры и вернуть массив этого «выращенного» набора точек дерева.
Я не могу даже Google достаточно информации, чтобы начать. Так что любая идея или ссылка, на которую я могу сослаться, или повторно использовать и внести некоторые коррективы, чтобы выполнить эту задачу. Я нашел несколько парсеров L-sys, но это выглядело как просто рисование на месте без контроля растущих направлений, а также не смог дать мне целые координаты точки.
Вероятно, это проблема, которую быстрее реализовать самостоятельно, а не искать и пытаться интегрировать некоторые сторонние библиотеки.
Реализовать L-системы довольно просто. Вам нужно реализовать 2 части.
Первая часть — это система перезаписи строк. Это просто. Вам просто нужно иметь словарь правил перезаписи (ключ ключа, строковое значение), а затем применять эти правила для начальной строки i-times (где i — количество итераций).
Псевдо-код:
map<char, string> rewriteRules = {{'L', "L+R+"}, {'R',"-L+R"}};
string rewrite(string str) {
string result = "";
for each (char c in str) {
if (rewriteRules contains key c) {
result += rewriteRules[c];
}
else {
result += c; // identity
}
}
}
Вторая, более сложная часть — это интерпретация результирующей строки символов. Самый простой способ интерпретации черепахоподобной графики в 3D — это использовать кватернионы — их легко объединить.
Правила переписывания, описанные выше, описывают кривую Дракона, а семантическое значение символов:
Следующие фрагменты кода демонстрируют реализацию перемещения и вращения в 3D с использованием кватернионов. Это от моего интерпретатора L-системы, написанного на C # (надеюсь, вы простите меня :).
Quaternion rotationQuat = Quaternion.Indentity;
Vector3D position;
Vector3D forwardVector = new Vector3D(1, 0, 0);
Vector3D upVector = new Vector3D(0, 1, 0);
Vector3D rightVector = forwardVector.Cross(upVector);
public void Forward(double distance, bool draw) {
Vector3D moveVector = rotationQuat.Transform(forwardVector * distance);
Vector3D oldPosition = position;
position += moveVector;
if (draw) {
// draw cylinder/box from oldPosition to (new) position
}
}
public void Yaw(double angle) {
rotationQuat *= new Quaternion(upVector, angle);
}
public void Pitch(double angle) {
rotationQuat *= new Quaternion(rightVector, angle);
}
public void Roll(double angle) {
rotationQuat *= new Quaternion(forwardVector, angle);
}
Таким образом, чтобы интерпретировать строку, вам просто нужно пройти строку и интерпретировать каждый символ. Самый простой способ — просто переключиться:
for each (char c in string) {
switch(c) {
case 'L':
case 'R':
Forward(10, true);
break;
case '+':
Yaw(90);
break;
case '-':
Yaw(-90);
break;
default:
break; // do nothing
}
}
Если вы хотите поэкспериментировать с L-системами (даже в 3D), есть хороший сайт http://malsys.cz где вы можете сделать это (эти фрагменты C # от него 🙂
Удачи с L-системами!
Я не знаю ни одной библиотеки с открытым исходным кодом, которая бы обеспечивала алгоритмы 3d L-системы, я подозреваю, что вам придется написать свою собственную.
Начните с реализации 2d, это довольно просто, википедия page — это хорошее место, где можно увидеть простые примеры, как только реализация 2d будет завершена, отсюда следует расширение до трети.