Текстовый формат GNU Octave
Материал из Xgu.ru
Автор: Владимир Кореньков
Правильная ссылка: http://xgu.ru/wiki/octave/txt_data_parser
Содержание |
[править] Постановка задачи
Достаточно часто текстовая информация представляется в строго формализованном виде, однако это представление отличается от желаемого, например, табличного (или подобного табличному) - типичным примером является формат какого-либо файла. По этой причине возникает необходимость в написании функций преобразования.
В качестве "лабораторного образца" выберем файл графического формата *.stl. Это один из промежуточных форматов представления данных о топологии поверхностей 3D модели. Фактически любая трехмерная поверхность (по крайней мере технически реализуемая на современном оборудовании) может бить интерполирована сеткой треугольников: вершины этих треугольников принадлежат поверхностям, а максимальное отклонение плоскости от профиля зависит от наперед заданной точности интерполяции. Особенностями stl-формата являются:
- направление вектора нормали к плоскости треугольника всегда указывает "наружу" детали;
- все координаты вершин являются положительными числами (если не заданы особые настройки при конвертировании);
- информация несколько избыточна, т.к. одна и та же точка должна принадлежать нескольким треугольникам.
Непосредственно сам файл имеет следующую структуру.
Пример описания одного треугольника в файле *.stl
solid Название файла
...
...
- facet normal CosA CosB CosC
- outer loop
- vertex x1 y1 z1
- vertex x2 y2 z2
- vertex x3 y3 z3
- endloop
- endfacet
endsolid
Задача состоит в том, чтобы извлечь информацию и представить ее в виде матрицы, например с названием Matrix:
Форма представления конечного результата
> Matrix
- x1 y1 z1 CosA CosB CosC
- x2 y2 z2 CosA CosB CosC
- x3 y3 z3 CosA CosB CosC
- ...
[править] Исходные данные
На сегодняшний день фактически каждая 3D CAD или дизайнерская система имеет в своем арсенале возможность импорта/экспорта stl-моделей. Поэтому для упрощения проверки результата в качестве 3D модели нарисуем параллелепипед и сохраним его с названием Cube.stl.
Содержимое файла Cube.stl
solid Cube
endsolid
- facet normal -1.000000e+000 0.000000e+000 0.000000e+000
- outer loop
- vertex 0.000000e+000 0.000000e+000 3.000000e+001
- vertex 0.000000e+000 4.500000e+001 3.000000e+001
- vertex 0.000000e+000 0.000000e+000 0.000000e+000
- endloop
- endfacet
- facet normal -1.000000e+000 0.000000e+000 0.000000e+000
- outer loop
- vertex 0.000000e+000 0.000000e+000 0.000000e+000
- vertex 0.000000e+000 4.500000e+001 3.000000e+001
- vertex 0.000000e+000 4.500000e+001 0.000000e+000
- endloop
- endfacet
- facet normal 0.000000e+000 -1.000000e+000 0.000000e+000
- outer loop
- vertex 6.000000e+001 0.000000e+000 3.000000e+001
- vertex 0.000000e+000 0.000000e+000 3.000000e+001
- vertex 6.000000e+001 0.000000e+000 0.000000e+000
- endloop
- endfacet
- facet normal 0.000000e+000 -1.000000e+000 0.000000e+000
- outer loop
- vertex 6.000000e+001 0.000000e+000 0.000000e+000
- vertex 0.000000e+000 0.000000e+000 3.000000e+001
- vertex 0.000000e+000 0.000000e+000 0.000000e+000
- endloop
- endfacet
- facet normal 1.000000e+000 0.000000e+000 0.000000e+000
- outer loop
- vertex 6.000000e+001 4.500000e+001 3.000000e+001
- vertex 6.000000e+001 0.000000e+000 3.000000e+001
- vertex 6.000000e+001 4.500000e+001 0.000000e+000
- endloop
- endfacet
- facet normal 1.000000e+000 0.000000e+000 0.000000e+000
- outer loop
- vertex 6.000000e+001 4.500000e+001 0.000000e+000
- vertex 6.000000e+001 0.000000e+000 3.000000e+001
- vertex 6.000000e+001 0.000000e+000 0.000000e+000
- endloop
- endfacet
- facet normal 0.000000e+000 1.000000e+000 0.000000e+000
- outer loop
- vertex 0.000000e+000 4.500000e+001 3.000000e+001
- vertex 6.000000e+001 4.500000e+001 3.000000e+001
- vertex 0.000000e+000 4.500000e+001 0.000000e+000
- endloop
- endfacet
- facet normal 0.000000e+000 1.000000e+000 0.000000e+000
- outer loop
- vertex 0.000000e+000 4.500000e+001 0.000000e+000
- vertex 6.000000e+001 4.500000e+001 3.000000e+001
- vertex 6.000000e+001 4.500000e+001 0.000000e+000
- endloop
- endfacet
- facet normal 0.000000e+000 0.000000e+000 1.000000e+000
- outer loop
- vertex 6.000000e+001 0.000000e+000 3.000000e+001
- vertex 6.000000e+001 4.500000e+001 3.000000e+001
- vertex 0.000000e+000 0.000000e+000 3.000000e+001
- endloop
- endfacet
- facet normal 0.000000e+000 0.000000e+000 1.000000e+000
- outer loop
- vertex 0.000000e+000 0.000000e+000 3.000000e+001
- vertex 6.000000e+001 4.500000e+001 3.000000e+001
- vertex 0.000000e+000 4.500000e+001 3.000000e+001
- endloop
- endfacet
- facet normal 0.000000e+000 0.000000e+000 -1.000000e+000
- outer loop
- vertex 6.000000e+001 4.500000e+001 0.000000e+000
- vertex 6.000000e+001 0.000000e+000 0.000000e+000
- vertex 0.000000e+000 4.500000e+001 0.000000e+000
- endloop
- endfacet
- facet normal 0.000000e+000 0.000000e+000 -1.000000e+000
- outer loop
- vertex 0.000000e+000 4.500000e+001 0.000000e+000
- vertex 6.000000e+001 0.000000e+000 0.000000e+000
- vertex 0.000000e+000 0.000000e+000 0.000000e+000
- endloop
- endfacet
[править] Пример решения
Поместим в одну директорию файлы Cube.stl и ниже приведенный StlToArray.m.
Файл StlToArray.m
function Array = StlToArray(FileName)
# определяем массив
- Array = [];
# создаем файловую переменную file и открываем файл FileName для чтения
- file = fopen (FileName,"r");
# просматриваем файл до конца (feof - end of file)
- while (! feof(file))
# переменной String присваиваем всю строку
- String = fgetl(file);
# переменная Pattern1 содержит шаблон для поиска направляющих косинусов вектора нормали плоскости треугольника,
# переменная Pattern2 - его координат вершин
# согласно приведенным ниже регулярным выражениям, поиск будет выполняться только в строках, содержащих
# слова "normal" или "vertex", и в виде отдельных элементов массива сохранять координаты -
# целостные фрагменты из цифр "0-9", разделителя дробной части ".", знаков "+" или "-" и обозначения степени "e"
- Pattern1 = 'normal\s*([0-9.+-e]*)\s*([0-9.+-e]*)\s*([0-9.+-e]*)';
- Pattern2 = 'vertex\s*([0-9.+-e]*)\s*([0-9.+-e]*)\s*([0-9.+-e]*)';
# выполняем поиск
# какие-то действия можно выполнять только если найдено совпадение подстроки с шаблоном Pattern1
- [s,e,te,m,t,nm] = regexp(String,Pattern1);
# параметр t является массивом из одного элемента, содержащего в себе подмассив интересующих нас координат,
- if (length(t) != 0)
# поэтому есть два пути: первый - создать вектор row, который будет состоять из 3-х элементов, и работать
# с этим вектором; второй - использовать доступ к cell array напрямую: t{1}{2} (см. ниже)
# преобразовываем все строки массива из текстового формата в числовой
- row = t{1};
- CosA = str2num(row{1});
- CosB = str2num(row{2});
- CosC = str2num(row{3});
- endif
# еще раз выполняем поиск
# если найдено совпадение подстроки с шаблоном Pattern2, формируем новую строку массива Array,
- [s,e,te,m,t,nm] = regexp(String,Pattern2);
# описывающую отдельную вершину треугольника
- if (length(t) != 0)
- X = str2num(t{1}{1});
- Y = str2num(t{1}{2});
- Z = str2num(t{1}{3});
- Array = [Аrray; X, Y, Z, CosA, CosB, CosC];
- endif
# закрываем файл
- endwhile
- fclose(file);
endfunction
Пример использования
> Matrix = StlToArray("Cube.stl");
> Matrix
В результате получим массив Matrix, состоящий из 36 строк и 6 столбцов, содержащий вершины треугольников и направляющие косинусы векторов нормалей (см. приведенный ниже вывод на экран) в удобном для работы виде.
0 | 0 | 30 | -1 | 0 | 0 |
0 | 45 | 30 | -1 | 0 | 0 |
0 | 0 | 0 | -1 | 0 | 0 |
0 | 0 | 0 | -1 | 0 | 0 |
0 | 45 | 30 | -1 | 0 | 0 |
0 | 45 | 0 | -1 | 0 | 0 |
60 | 0 | 30 | 0 | -1 | 0 |
0 | 0 | 30 | 0 | -1 | 0 |
60 | 0 | 0 | 0 | -1 | 0 |
60 | 0 | 0 | 0 | -1 | 0 |
0 | 0 | 30 | 0 | -1 | 0 |
0 | 0 | 0 | 0 | -1 | 0 |
60 | 45 | 30 | 1 | 0 | 0 |
60 | 0 | 30 | 1 | 0 | 0 |
60 | 45 | 0 | 1 | 0 | 0 |
60 | 45 | 0 | 1 | 0 | 0 |
60 | 0 | 30 | 1 | 0 | 0 |
60 | 0 | 0 | 1 | 0 | 0 |
0 | 45 | 30 | 0 | 1 | 0 |
60 | 45 | 30 | 0 | 1 | 0 |
0 | 45 | 0 | 0 | 1 | 0 |
0 | 45 | 0 | 0 | 1 | 0 |
60 | 45 | 30 | 0 | 1 | 0 |
60 | 45 | 0 | 0 | 1 | 0 |
60 | 0 | 30 | 0 | 0 | 1 |
60 | 45 | 30 | 0 | 0 | 1 |
0 | 0 | 30 | 0 | 0 | 1 |
0 | 0 | 30 | 0 | 0 | 1 |
60 | 45 | 30 | 0 | 0 | 1 |
0 | 45 | 30 | 0 | 0 | 1 |
60 | 45 | 0 | 0 | 0 | -1 |
60 | 0 | 0 | 0 | 0 | -1 |
0 | 45 | 0 | 0 | 0 | -1 |
0 | 45 | 0 | 0 | 0 | -1 |
60 | 0 | 0 | 0 | 0 | -1 |
0 | 0 | 0 | 0 | 0 | -1 |
GNU Octave Инсталляция |
Синтаксис языка |
Командная строка
|
---|