Предлагаю эту тему для вопросов и ответов, касающихся написания кодов для TeX-совместимой рисовалки Asymptote.И для затравки предлагаю первый вопрос:
Каким образом обеспечивается гладкое склеивание патчей, из которых строятся поверхности?Раскрою суть вопроса подробнее. Поверхности (в коде Asymptote они определяются структурой surface) составляются из четырёхугольных заплаток -- патчей, которые в коде определяются структурой patch. То бишь атрибут
поверхности является массивом патчей. Соответственно, каждый патч имеет атрибут
, который представляет собой двумерный размера
массив точек (объектов типа triple). Точки этого массива имеют такой смысл:
1)
,
,
и
являются жёстко фиксированными углами заплатки.
2)
,
,
,
,
,
,
и
являются парами "контрольных точек" для соответствующих сторон. Т.е. они не обязательно лежат на границе заплатки, но направление, под которым выходит линия соответствующей границы из соответствующего угла, обязательно является направлением на соответствующую контрольную точку.
3)
,
,
и
являются т.н. "внутренними" точками патча. И мой вопрос касается именно их функций, ибо в документации никаких подробностей про них я не нашёл. (В то время как принцип построения кривых Безье -- которыми в том числе рисуются и границы заплатки -- в книжке "Andy Hammerlindl, John Bowman, and Tom Prince. Asymptote: the Vector Graphics Language" описан очень понятно).
Например, если посмотреть, какой объект создаётся командой unitsphere, то можно обнаружить, что эта поверхность состоит из восьми патчей такого типа:
Здесь для наглядности помимо системы координат показаны 16 зелёных точек, определяющих патч, а также в квадратных скобках указано каким индексам массива соответствует каждая точка. Нетрудно заметить, что в данном случае четырёхугольная заплатка превращена в треугольную, благодаря тому, что одна из её сторон взята нулевой длины (см. верхний угол). На первый взгляд здесь всё понятно: Например, точки
и
определяют форму нижней границы. Соответственно, точка
, например, имеет единичную координату
и такую же координату
, как у точки
, что очевидно гарантирует тот факт, что поверхность подходит к нижней границе вертикально.
Но дело в том, что в этом случае у заплатки все углы прямые, а поэтому всё выглядит достаточно простым, но в жизни не всегда может быть так. На самом деле можно создать заплатку даже с развёрнутым углом (т.е. 180 градусов). И вот здесь у меня возникают непонятки с алгоритмом построения. Скажем, я захотел покрыть одной заплаткой не осьмушку сферы (как в вышеприведённом примере), а сразу четвертушку. В таком случае я пишу такой простенький код:
Код:
path halfcircle=arc((0,0),1,0,180);
path3 XYhalfcircle=path3(halfcircle);
path3 XZhalfcircle=reverse(rotate(90,X)*XYhalfcircle);
surface S=surface(XYhalfcircle&XZhalfcircle&cycle);
Т.е. я построил полуокружность, повернул её на 90 градусов вокруг прямой, проходящей через концы, а потом на получившийся замкнутый контур натянул поверхность. Разумеется, в итоге всё же получим не четвертушку сферы, а сегмент эллиптического цилиндра:
Но это поправимо. Главное, что мы видим, что эта поверхность состоит из одного патча, причём два из его чертырёх углов (
и
) являются развёрнутыми! Теперь, в надежде на превращение этого патча в нечто похожее на четвертушку сферы, мы должны как-то откорректировать положение внутренних точек. Первое, что приходит в голову, это расставить их примерно так же, как в примере со сферическим треугольником. Т.е. ниже добавляем код:
Код:
triple[][] P=S.s[0].P;
P[1][1]=(1,P[1][0].y,P[0][1].z);
P[1][2]=(0,P[1][0].y,1);
P[2][1]=(0,1,P[0][1].z);
P[2][2]=(-1,P[3][2].y,P[2][3].z);
Увы, то, что наблюдается на картинке, далеко не похоже на сегмент сферы. В частности, поверхность подходит к нижней границе в области её (границы) середины совсем не вертикально:
Поскольку в области углов (которые по 90 градусов) эта фигура больше всего похожа на часть сферы, можно сделать очевидный вывод, что с точками
и
всё в порядке, а вот с точками
и
надо что-то менять. Опытным путём я подобрал такое решение:
Код:
P[1][2]=(0,1+P[1][0].y,1+P[0][1].z);
P[2][1]=(0,1+P[1][0].y,1+P[0][1].z);
Результат получается ОЧЕНЬ похож на четвертушку сферы. Хотя всё же не идеально. Если убрать прозрачность и пристыковать к этой фигуре снизу её зеркальное отражение относительно плоскости XY, то становится виден шов:
Я не понимаю: Можно ли как-то рассчитать положение внутренних точек, чтобы стык был совершенно гладким?