Глава 5. Параметрическое пространство Наши исследования геометрии отмечают объекты в пространстве; цифровое представление формы и тектонику; различные сочленения элементов и множество процессов генерации формы, от классических представлений о симметрии и паттернах до NURBS и полигональных сеток. Мы имеем дело с объектами. Эти объекты могут быть кубами, шарами, конусами, кривыми, поверхностями или любой их комбинацией. С точки зрения своего присутствия в пространстве, они обычно делятся на точки (0-мерные объекты), кривые (1-мерные), поверхности (2-мерные) и твердые тела (3-мерные объекты). Мы задаем пространство системой координат, для определения некоторых основных свойств, такие как местоположение, направление движения и измерения. Декартовой системой координат является 3-мерное пространство, которое имеет точку отсчета O = (0,0,0) и три оси, пересекающиеся под прямыми углами в этой точке, которые задают направления X, Y и Z. Но мы должны также рассматривать, что эта трехмерная система координат также включает в себя двумерную (плоскость (X, Y)) и одномерную (ось(X)) системы. То что нам известно как параметрическое проектирование, имеет дело с этими пространствами. Мы должны пройти через эти пространства для "параметрического" дизайна с помощью кривых и поверхностей. Хотя параметрический дизайн перемещается между этими пространствами, мы должны понимать их как параметрические пространства.
5.1. Одномерное (1D) параметрическое пространство Ось X является бесконечной прямой, на которой заданы некоторые числа, связанные с различными позициями на ней. Просто X = 0 означает начало координат, а х = 2,35 точку в положительном направлении вдоль оси Х, расстояние до которой 2,35 единицы от начала координат. Эта простая, одномерная система координат может быть параметризована на любую кривую в пространстве. Однако не только мировая ось Х имеет некоторые действительные числа, связанные с различными позициями на ней, но и любая кривая в пространстве имеет возможность быть параметризованной рядом действительных чисел, которые показывают различные позиции по кривой. Так в нашем 1D параметрическом пространстве, когда мы говорим о точке, которая может быть описана вещественным числом, то имеем дело с числом которое связано с определенной точкой на кривой. Важно знать, что, поскольку мы работаем сейчас не с мировой осью X, то любая кривая имеет свое собственное пространство параметров и эти параметры не соответствуют в точности универсальной системе измерения. Любая кривая в Grasshopper имеет параметрическое пространство, начинающееся от нуля и заканчивающееся положительным числом (см. рис.).
Рис. 105. Одномерное параметрическое пространство на кривой. Любые значения "t" являются действительными числами, связанными с положением на кривой. Так как мы говорим о кривой и ссылаемся на некоторые конкретные точки на ней, нам не обязательно всегда иметь дело с точками в 3D пространстве р = (X, Y, Z), но мы можем задать точку на кривой Р = Т в качестве конкретного параметра на ней. И очевидно, что мы всегда можем преобразовать это параметрическое пространство в точку, в мировой системе координат (Рис. 106).
Рис. 106. Одномерное параметрическое пространство и перевод его в трехмерную систему координат.
5.2. Двумерное (2D) параметрическое пространство Две оси X и Y в мировой системе координат связанны с точками на бесконечной плоской поверхности таким образом, что каждая точка в этом пространстве, задается парой чисел р=(X, Y). Совершенно так же, как в случае 1D пространства, здесь мы можем представить себе, что все значения 2D пространства можно проследить не только в координатах плоскости, но и на любой поверхности в пространстве. Поэтому мы можем параметризовать систему координат на поверхности, и задать ее различные точки в виде пар чисел, известных как UV пространство, в котором любая точка P на поверхности задается в виде: P = (U, V). Чтобы найти точку, мы опять не должны работать с тремя значениями P = (X, Y, Z), как с 3D-пространством. А вместо этого мы можем работать с UV "параметрами" поверхности. (см. рис.)
Рис. 107. Координаты UV и 2D параметрическое пространство Эти "Параметры" являются специфическими для каждой поверхности самой по себе, и они не являются общими, такими как мировая система координат. Поэтому мы называем их параметрическими! Снова мы имеем доступ к 3D эквивалентам координат любой точки на поверхности.
Рис. 108. Эквивалент точки P=(U,V) в мировой системе координат p=(X,Y,Z)
5.3. Переход между пространствами Важной частью в параметрическом мышлении дизайнера является точное знание, в какой системе координат или пространстве параметров мы должны работать, для того, чтобы получить результат. Работая с кривыми и поверхностями, мы должны задавать данные для пространства параметров, но мы всегда должны идти вперед и назад в мировой системе координат, чтобы предоставлять данные для другого создания геометрии или преобразований. Это наиболее сложно при написании сценариев, но так как grasshopper имеет визуальный интерфейс, а не код, вы можете просто определить, какой вид данных необходимо предоставить для достижения цели вашего дизайна. Здесь отметим, что для того чтобы использовать геометрию в Grasshopper, это не всегда должен быть параметр или значение в системе координат. Иногда нам нужен просто порядковый номер. Если мы работаем с множеством точек, линий или любых других объектов, и они были получены, как группа объектов, как облако точек, то каждый объект связан с натуральным числом, которое показывает положение его в списке всех объектов. И нам просто нужно задать номер объекта, в качестве его "индекса", а не какой-либо системе координат. Индексация массива переменных, как в программировании, основана на системе подсчета от нуля (т.е. индекс первого объекта равен нулю). (см. рис.)
Рис. 109. Порядковый номер в группе объектов, это простой способ выбора по одному. Нумерация объектов начинаются с 0. Так как уже отмечалось выше, в ассоциативном моделировании мы генерируем нашу геометрию шаг за шагом, как некоторые связанные объекты. По этой причине мы идем в пространство параметров каждого объекта и извлекаем конкретную информации о нем и используем ее в качестве исходных данных для следующего шага. Так моделирование может быть начато из простого поля точек в качестве основных генераторов, а заканчиваться мелкими деталями результирующей модели, в различных иерархиях.
5.4. Основные параметрические компоненты 5.4.1. Вычисление кривой Компонент <evaluate> - это функция, которая находит точку на кривой или поверхности, на основе задаваемого значения параметра. Компонент <evaluate curve> (Curve > Analysis > Evaluate curve) берет кривую и параметр (число) и возвращает точку на кривой по этому параметру.
Рис. 110. Вычисленная точка на кривой <curve> для конкретного параметра, который задан с помощью <number slider>
Рис. 111. Мы можем использовать любую <curve>, что нарисована в Rhino или в Grasshopper в компоненте <evaluate>. И вы видите, что мы можем использовать последовательность чисел <series> в качестве параметров <evaluate> вместо одного параметра. В приведенном выше примере, потому что некоторые числа компонента <series> больше, чем область значений параметра кривой, вы видите, что компонент <Evaluate> дает нам предупреждение (становится оранжевым) и, что точки расположены на мнимом продолжении кривой.
Рис. 112. Хотя выход 'D' в компоненте <curve> дает нам область определения кривой (минимальный и максимальный параметры кривой), в качестве альтернативы мы можем задать внешний компонент <curve> и в его контекстном меню включить опцию Reparameterize (репараметризация). Она устанавливает область определения кривой от 0 до 1. Поэтому мы можем отслеживать длину всех <curve> с помощью <number slider> или любого числового множества между 0 и 1, а не быть обеспокоены тем, что параметры могут выходить за рамки области определения кривой. Другие полезные компоненты для параметрического пространства располагаются в Curves > Analysis / Division, и мы будем говорить о них позже. 5.4.1. Вычисление поверхности Если для оценки кривой нам нужно число в качестве параметра (так как кривая имеет 1Dразмерность), то для поверхностей, в качестве параметров нам нужны пары чисел (U, V). С помощью них, мы можем вычислять конкретные точки на поверхности. Мы используем компонент <evaluate surface> (Surface > Analysis > Analysis), чтобы вычислить точку на поверхности для заданных параметров.
Мы можем просто использовать компонент <Point> для оценки поверхности, используя ее как UV вход компонента <Evaluate surface> (он игнорирует Z размерность). При этом вы можете отслеживать ваши точки на поверхности только по координатам X и Y компонента <Point>, как по параметрам U и V.
Рис. 113. Точка вычисляется <Evaluate> на поверхности <surface> на основе параметров U, V задаваемых парой чисел <number slider>, в качестве координат компонента <Point>. Так же, как и для кривых, вы можете использовать опцию"Reparameterize" в контекстном меню <surface>для того чтобы привести область определения поверхности к диапазону от 0 до 1 в обоих направлениях U и V. Измените с помощью <number slider> U, V и посмотрите, как вычисляемая точка движется по поверхности (мы переименовали X, Y, Z входы компонента в U, V, -).
Рис. 114. Так как нам нужны <points>, чтобы вычислить<surface>, то мы можем использовать любой метод, который мы использовали для создания точек. Наши возможности не ограничиваются только парой параметров задаваемых <number slider> , и мы можем отследить поверхность очень многими различными способами.
Рис. 115. Чтобы разделить поверхность (как в примере выше) на несколько строк и столбцов можно использовать <Divide surface> или, если нам нужно несколько плоскостей,
проходящих через определенные строки и столбцы поверхности, то мы можем использовать <surface frame> из Surface> Util. 5.4.3. Ближайшая точка на кривой и поверхности Нам не всегда известно значение параметра для поиска точки. Иногда у нас есть точка и мы хотим знать ее параметры для дальнейшего использования. Помочь в этом может нахождение ближайшей точки. Компоненты <Curve CP> и <surface CP> (ближайшая точка кривой / поверхности) помогают нам сделать это.
Рис. 116. <Curve Cp> и <Surface CP> помогают нам найти параметр точки на кривой или поверхности. Другие компоненты, могут использовать полученные параметры.
5.5. Размножение объектов в параметрическом пространстве По многим причинам дизайнеры используют поверхности для размножения на них некоторых других геометрических объектов. Поверхности являются гибким продолжением двумерных объектов, что являются подходящими для этой цели. Есть несколько методов решения задачи распространения объектов по поверхности, но здесь мы собираемся начать с одной из самых простых. А другие методы мы будем обсуждать позже. У нас есть криволинейная поверхность и простая геометрия, например параллелепипед (box). Вопрос в том, как мы можем распространить этот объект (box) по поверхности, таким образом, чтобы мы имели контроль на макроуровне (могли изменять поверхность) и микроуровне (box), для дизайна их по отдельности, но с помощью ассоциативного метода. Метод таков: Для того, чтобы выполнить задачу, мы должны разделить поверхность на нужное число частей и генерировать наши объекты (box) на этих конкретных местах на поверхности. А затем подрегулировать их, если мы хотим провести местные манипуляции с этими объектами. Создание желаемых точек на поверхности легко. Мы можем разделить поверхность или мы можем сгенерировать некоторые точки, на основе любых численных данных, которые мы хотим.
Для местных манипуляций распространяемой геометрии, нам опять понадобятся некоторые числовые множества данных, которые могут быть использованы для таких преобразований, как вращение, местные перемещения, изменения размеров, регулирование и т.д.
Рис. 117. Репараметризованная поверхность <surface> свободной формы вычисляется <evaluate> на основании числового диапазона <range> от 0 до 1, разделенного на 30 шагов с помощью <number slider> в обоих направлениях U и V. (Здесь вы можете использовать <divide surface>, но мы использовали компонент <Point>, чтобы напомнить вам технику генерации всех точек из главы 2, как возможный вариант для использования в этом эксперименте).
Рис. 118. Как видите, компонент <evaluate> возвращает на выходе "нормаль" и "плоскость" любой вычисляемой точки на поверхности. Мы использовали эти плоскости (или фреймы) для создания на них серии параллелепипедов <box>. А их размеры контролируются компонентом<number slider>. Для построения компонента <box> (surface>primitive> center box) необходимо задать точку центра объекта, и его размеры по X, Y и Z. Для локальной манипуляции параллелепипедов, мы просто повернем их на своих местах. Мы хотим установить ось вращения параллельно направлению U поверхности и в нашем случае относительной простой поверхности мы собираемся выбрать плоскость XZ в качестве базовой плоскости для их вращения (см. рис.).
Рис. 119. Локальное вращение объекта
Рис. 120. Компоненту <rotate> необходимо три параметра. Первый – это геометрия, которая означает наши компоненты <box> . Вторым пунктом является угол поворота. Мы хотим, повернуть их на случайные значения угла (вы можете вращать их постепенно или любым другим способом). Поэтому мы создали набор случайных чисел <random>. Количество случайных чисел равно числу параллелепипедов. Для определения этого мы использовали компонент <list length>, возвращающий длину списка. Наконец, чтобы определить плоскости оси вращения, мы создали <XZ plane> в каждой точке, где вычисляется <evaluate> поверхность <surface> и подключили их к к компоненту <rotate>. Не забудьте отключить предварительный просмотр предыдущих созданных компонентов, для повышения производительности процесса.
Рис. 121. Конечная геометрия
Рис. 122. Попробуйте объединить различные концепции в ваших проектах. Здесь вместо случайных величин для вращения кубиков, мы использовал точечный аттрактор и
установили его расстояние от каждого кубика, а затем использовали расстояние в качестве фактора вращения. И как видите, получили новые результаты, приведенные в эксперименте. Эти методы применялись для местных манипуляции параллелепипедов, но вы знаете, что вы могли бы применить изменения в глобальном масштабе. Использование неравномерного вычисления Почему мы всегда используем равномерное распределение точек на поверхности и добавляем компоненты к нему? Можем ли мы установить определенный критерий и вычислить нашу поверхность на основе этого, а затем выбрать конкретную позицию на поверхности? Или так как мы используем пространство параметров U, V и последовательные наборы данных (или дополнительных циклы в сценарии) мы всегда ограничены прямоугольным делением на поверхности? Есть пара вопросов, касающихся параметрического отслеживания поверхности, но здесь мы буду иметь дело с простым примером, чтобы показать, как в определенных ситуациях мы можем использовать некоторые из U, V параметров поверхности и не равномерную прямоугольную сетку на них. Пример с колоннами У нас есть две поверхности свободной формы, покрывающих пространства. Имеется в виду создание социального открытого пространства между ними. Мы хотим добавить несколько столбцов между этими поверхностями, а поскольку поверхности свободной формы, то мы не хотим, чтобы была сетка колонн. Решено было ограничить длину столбца и добавить их в тех местах, где расстояние между поверхностями не превышает определенного предела . Мы хотим добавить два перевернутых пересекающихся конуса в виде столбцов в этом пространстве, только потому, чтобы сделать простой формы.
Рис. 123. Мы задали две поверхности в Rhino, передали их в Grasshopper с помощью <srf_top> и <srf_bottom>, как охватывающие пространство и репараметризовали (Reparameterized). Мы также сгенерировали числовой диапазон <range> между 0 и 1. Разделили его на <number slider>, и с помощью компонента <Point> вычислили <evaluate> точки <points> этих поверхностей.
Рис. 124. Далее, мы создал кучу линий <line> между всеми этими точками, а также измерили расстояние между любыми двумя точками.
Рис. 125. Теперь нам нужно извлечь желаемые линии из списка. Чтобы выбрать наши линии здесь мы использовали компонент <dispatch> (Sets> List> Dispatch). Компонент <dispatch> использует булевы данные, которые связаны с данными из списка, чтобы передать тех, кто связан со значение True на выход А. А те, что связаны с False, попадают на выход B. Булевы данные поступают от простой функции сравнения. В этой <function> мы сравнили длину линии с заданным числом, как максимальной длиной линии (X> Y, X = <number slider>, у = <distance>). Любая строка длиной менее <number slider> создает значение функции True, и передает его через <dispatch> компонент для дальнейшего производства. Так что, если мы используем линии с выхода А <dispatch> , то можем быть уверены, что они все меньше определенной длины, поэтому они будут нашими колоннами.
Рис. 126. Геометрия колонн представляет собой два перевернутых конуса, которые пересекаются своими вершинами. Поскольку у меня сеть ось колонны, я хочу сделать два круга на концах оси, а затем выдавить их до точек на кривой, которые делают это пересечение возможным.
Рис. 127. С помощью компонента <End points>мы можем получить оба конца колонны. Мы используем эти точки, как базисные точки, чтобы сделать окружности <circle> данного радиуса. Вы уже знаете, что эти окружности являются плоскими, но наши поверхности не являются плоскими. Поэтому нам нужно спроецировать наши окружности на поверхности, чтобы получить их скорректированную форму. По этой причине мы использовали компонент <project> (Curve > Util> Project). К входу B компонентов<project> подключены верхняя и нижняя поверхности.
Рис. 128. Последним шагом будет выдавливание этих спроецированных окружностей к определенным точкам на оси колонн (см. рис.). Мы использовали компонент <extrude Point>, а в качестве базовых кривых указали спроецированные кривые. Для задания точки, до которой производится выдавливание, присоединили оси всех колонн к компоненту <curve> и репараметризовали их. А затем вычислили <evaluate> на них точки в двух конкретных значениях параметров: 0,6 для верхнего конуса и 0,4 для нижнего конуса.
Рис. 129. Хотя в этом примере, мы снова использовали сетку с отслеживанием хода поверхности, но мы использовали дополнительные критерии, чтобы выбрать несколько точек, а не все из них равномерно.
Рис. 130. Финальная модель Идея использования пространства параметров кривых и поверхностей к размножению объектов на них имеет много вариантов и методов. Не будем зацикливаться на них и попытаемся исследовать больше. Мы увидим, немного больше.
5.6. Деревья данных Ведя разговор о параметрическом пространстве и использовании соответствующих компонентов, настало время открыть новую тему об управлении данными в Grasshopper, которая называется 'Data Tree' (дерево данных). Данное понятие потребуется вам со временем при работе со сложными моделями, особенно в параметрическом пространстве. Один из главных потенциалов процедурных методов состоит в том, что они позволяют нам манипулировать и управлять сотнями объектов имеющих ассоциативные связи. Работая с таким большим количеством объектов иногда нам нужно применить команды ко всем этим объектам, а иногда нужно извлечь отдельные элементы и применить команды только к ним. Поэтому мы должны иметь доступ к нашим объектам и управлять нашими данными (объектами) разными способами. На изображении ниже мы видим 5 кривых, каждая из которых разделена на 10 частей. Мы хотим извлечь вторые точки каждой кривой и соединить их друг с другом новой интерполяционной кривой.
Рис. 131. Компонент <curve>, содержащий 5 кривых, каждая из которых делится компонентом <Divide> на 10 частей. Если выбрать с помощью компонента <item> точки с индексом 1, то можно увидеть, что выделились все вторые точки кривых. Замечательно! Но если вы присоедините эти точки к компоненту <interpolate>, для того чтобы соединить их кривой, то вы увидите что компонент выдает ошибку и ничего не рисует. Для понимания проблемы позвольте познакомить вас с одним полезным компонентом и немного прояснить ситуацию. Этот компонент называется <Param Viewer> (Params>Special). Сравните результат:
Рис. 132. Компонент <Param Viewer> показывает некоторую информацию о данных внутри компонентов, которая является причиной ошибки в компоненте <interpolate>. То, что вы видите в <Param Viewer> - это концепция дерева данных в Grasshopper. Как видно на рисунке выше, компонент <curve> содержит 5 элементов. Но когда эти кривые делятся с помощью <divide> и создаются некоторые точки для каждой кривой, то эти точки сортируются по разным спискам данных, которые называются Branches (ветви). Это означает, что результат операции <Divide> - это не один список данных из 55 точек, а пять списков, каждый из которых содержит 11 точек. Таким образом, исходные данные «Дерева» делятся на «Ветви», для обеспечения дальнейшего использования и более простого доступа к ним в процессе проектирования. Вот почему, когда мы выбрали с помощью <item> элементы списка с индексом 1, то выделились элементы с индексом 1 из каждого списка.
Рис. 133. <Param Viewer> с включенной опцией ‘Draw Tree’ (доступна в контекстном меню компонента) отображает различие между ветвями данных в каждом компоненте. Почему <interpolate> не рисует кривую? В чем проблема? Взглянем подробнее на информацию, которую мы получаем в нашей ситуации:
Рис. 134. Компоненты <Param Viewer> и <Panel>: а) кривые, б) выбранные точки с индексом 1.
На рисунке а) <Param Viewer> показывает только одну главную ветвь данных, а если посмотреть на компонент <Panel>, то мы увидим список кривых под заголовком {0}. В Grasshopper фигурные скобки {} применяются для обозначения дерева данных и показывают ветвь дерева, в которой располагается объект. Поскольку все кривые на первом рисунке обозначены {0}, это означает, что они располагаются на главной ветви дерева. Если вернуться к Рис. 132, то мы увидим, что <Param Viewer>, подключенный к <curve> отображает (Paths=1). Это означает, что мы имеем только одну ветвь данных и в этой ветви ({0} N=5) мы имеем 5 элементов данных. На Рис. 134 б) видно, что данные после элемента <item> принадлежат пяти различным ветвям: {0:0}, {0:1}, …, {0:4} и содержат по одной точке в каждом списке. Если мы снова вернемся к Рис. 132, то увидим, что третий <Param Viewer> имеет 5 ветвей (psths=5) и каждая ветвь данных содержит по одному элементу (N=1 для всех ветвей). Это означает, что данные разделены по разным ветвям и когда они передаются компоненту <interpolate>, то каждый элемент передается отдельно от остальных и <interpolate> не может начертить полилинию по пяти отдельным точкам. Как же решить эту проблему?
Рис. 135. Для решения этой проблемы мы использовали компонент <Flatten> (Sets>Tree), который конвертирует данные из нескольких ветвей в одну, что и видно в <Param Viewer>. Как видно на втором компоненте <Panel>, теперь у нас есть пять точек, принадлежащих ветви {0} и поэтому компонент <interpolate> может построить полилинию по этим пяти точкам.
Обобщая полученные результаты, необходимо понимать, что при работе с несколькими объектами на разных уровнях, данные имеют иерархическую структуру, подобно дереву. И каждая ветвь этого дерева имеет свой собственный путь в виде индекса, который показывает
уникальный адрес этой ветви (напр.: {0:1}). При работе с компонентами управления списками, важно знать, что эти компоненты работают с каждой ветвью дерева, как с отдельным списком. Нам нужно уметь генерировать ветви данных сами по себе, конвертировать данные в одну ветвь, а также знать другие способы управления данными, которые мы попытаемся показать в дальнейших экспериментах.
Рис. 136. Ветви дерева данных, отображаемые с помощью компонента ‘DATA Tree’. Рассмотрим пример для закрепления темы: Мы хотим разработать поверхность с прорезями, подобную той, что изображена на рисунке ниже. Эта поверхность должна базироваться на задаваемой пользователем поверхности.
Рис. 137. Эскиз разрабатываемой поверхности.
Для построения такой поверхности мы хотим создать некоторое количество отрезков на верхнем и нижнем ребрах исходной поверхности и затем соединить их с помощью операции лофтинга. Также нам нужно контролировать направление этих маленьких отрезков, чтобы управлять степенью отклонения поверхностей, т.е. размером прорезей.
Рис. 138. Поверхность загружена в Grasshopper с помощью компонента <surface>. С помощью <BRep Components> (Surface>Analysis) мы получаем доступ к ее составляющим (в нашем случае к ребрам). Затем выбраны нижнее и верхнее ребра, с помощью компонента <item> по индексам 0 и 2.
Рис. 139. Мы использовали нижнее ребро для создания смещенной кривой с помощью <offset> (Curve>Util), а также поменяли направление верхнего ребра на противоположное компонентом <Flip> (Curve>Util), т. к. нам известно, что кривые верхнего и нижнего ребер имеют разную ориентацию (порядок нумерации вершин). Компоненты <divide> использованы для деления этих граничных кривых и получения множества точек. (Мы могли бы использовать один <divide> для обеих кривых, но это сделать сложнее).
Рис. 140. Компонент <line> использован для соединения отрезками точек деления нижнего ребра и соответствующих им точек смещенной кривой. Второй <line> соединяет отрезками точки деления верхнего ребра с соседними точками списка (shift offset = 1).
Рис. 141. Если мы теперь используем компоненты <line> для построения поверхностей лофтинга <loft>, то увидим, что поверхность создается не так как мы планировали, и даже использование компонента <weave> не помогает в этой ситуации.
Рис. 142. Посмотрев <param viewer> компонентов <line>, можно заметить, что оба компонента имеют только одну ветвь данных. Когда строится поверхность лофтинга, то при построении используются все отрезки, без разделения их на пары. Но нам здесь нужно, чтобы отрезки принадлежали разным спискам данных. Тогда при построении поверхности лофтинга, будут использованы попарно отрезки из двух разных списков.
Рис. 143. Для решения этой проблемы мы использовали компонент <Graft> (Sets>Tree>Graft Tree). Как вы видите, в результате работы компонента списки данных, обоих <line> разделились на ветви, по одному элементу данных на каждую ветвь. Теперь компонент <loft> соединяет каждый отрезок из первого списка с соответствующим ему отрезком из второго списка. И мы видим, что результирующая геометрия напоминает наш эскиз. Здесь, в противоположность первому примеру мы сортируем наши данные по разным ветвям, чтобы получить в результате несколько поверхностей вместо одной непрерывной поверхности.
Рис. 144. Здесь мы хотим напомнить, что если вы теперь захотите нарисовать интерполяционную кривую через точки, вычисляемые на полученных поверхностях, то необходимо применить к вычисленным точкам компонент <Flatten>. Это нужно для объединения точек в одну ветвь, т.к. вычисленные точки принадлежат разным ветвям дерева данных. В различных ситуациях разработки и дизайна поверхностей требуется направлять данные в разные ветви или объединять в одну. Помочь нам в этом могут компоненты, расположенные на вкладке Sets>Tree.