Глава 13  ◄     Содержание     ►   Глава 15

Three.js и геометрия.   Глава 14.   Рундист огранки маркиз (marquise)

В качестве направляющей линии для цилиндра рундиста берутся или две пересекающиеся дуги окружности или две пересекающиеся дуги эллипса. Программа в работе показана ниже.

Расчет и отрисовка на холсте формы рундиста

На рисунке 1 показан первый этап построения линии рундиста огранки. Окружность, центр которой расположен в точке A, пересечена справа от ее центра осью OY. Точка пересечения B окружности с осью OY определяет положение острия рундиста. Обычно это острие называют носиком рундиста (и всей огранки в целом). Дуга окружности BC представляет собой лишь одну четвертую часть линии рундиста. Остальные три четверти линии рундиста, если найдена дуга BC, можно определить исходя из соображений симметрии. Сначала рассмотрим вариант, когда линия рундиста строится на основе дуги окружности.

Исходными данными для расчета центра окружности A и радиуса окружности, который на рисунке 1 представлен отрезком AB, является положение точек B и C. Будем считать, что относительная ширина огранки при проведении расчетов связанных с построением формы рундиста равна 2.0. В дальнейшем мы приведем относительную ширину огранки к значению равному 1.0, которое ранее мы условились принимать за стандартную относительную ширину огранки (и рундиста).

Расположим окружность с центром в точке A относительно оси OY таким образом, чтобы координаты точки C по оси OX стали равны половине ширины огранки, а по оси OY приняли нулевое значение. В этом случае точка B, расположенная на острие рундиста, имеет координаты (0.0, - u). При значении ширины огранки равной 2.0, длина огранки равна значению 2.0 • lw. Значение u можно найти исходя из величины удлинения огранки lw и принимая во внимание тот факт, что ширина огранки по оси OX (рисунок 1) равна 2.0. Из этого следует, что значение величины u оказывается равной величине удлинения огранки lw.

Еще раз, чтобы в дальнейшем не возникло недопонимание в связи со значением ширины огранки, уточним сказанное выше. В функции InitGirdle для огранки маркиз, также как и в одноименной функции InitGirdle из огранок пирамида и бриллиант, значение ширины огранки принимается равной 1.0. Но для удобства расчета на предварительном этапе расчета мы принимаем, как это видно из рассмотрения рисунка 1, в огранке маркиз значение ширины рундиста (и огранки), равное 2.0. Поэтому, после того как расчет формы рундиста маркиза будет завершен, следует все значения координат вершин рундиста по осям OX и OY разделить на число 2.0 для приведения нормированной ширины огранки к значению 1.0. Это будет иметь значение когда мы перейдем к созданию трехмерной модели на основе расчитанного рундиста огранки.

Заметим еще, что для огранок пирамида и бриллиант удлинение огранки задавалось вдоль оси OX, а на рисунках 1 и 2, а также в самой программе, удлинение задано вдоль оси OY (отрезок OB равен половине длины огранки). Для того чтобы и в огранке маркиз ширина измерялась вдоль оси OY, а длина вдоль оси OX, в дальнейшем (в 3D-модели), при расстановке вершин на рундисте, мы развернем огранку таким образом, чтобы ее удлинение задавалось стандартным образом – вдоль оси OX. Те, кто пожелает более глубоко познакомиться с расчетом формы рундиста, могут прочитать приведенную далее врезку. Заметим, что для того, чтобы вид рундиста в программе стал подобным тому, который приведен на рисунке 2, в программе следует значение параметра δ отрицательным. В тексте программы (и на рисунке 2) для параметра δ используется переменная vp.

Разбиение рундиста на сегменты

Рассмотрим процесс разбиения рундиста на сегменты. Будем считать, что рундист состоит из 64 сегментов. Сделаем разбивку только для одного квадранта. Для остальных квадрантов координаты вершин рундиста можно определить исходя из соображений симметрии огранки. Самой простой способ выполнить эту задачу состоит в том, чтобы разделить дугу BC рундиста (рисунок 2) на 16 равных частей. Подобным образом, мы поступали при расстановке вершин на рундисте бриллианта.

Но можно поступим поступить иначе – деление провести в два этапа. На первом этапе можно разделить дугу BC на четыре сегмента. Деление следует произвести таким образом, чтобы можно было задавать размеры каждого из четырех сегментов. Для этого потребуется ввести допонителный параметр (или несколько параметров) в СДМ. На втором этапе потребуется разделить каждый получившийся сегмент еще раз, но теперь уже (скорее всего) на четыре равные части. Такой способ разбивки рундиста на сегменты позволит изменять положение его узловых вершин. Это в свою очередь даст возможность изменять форму короны и павильона огранки, так как она во многом определяется положением вершин на рундисте. Однако для простоты мы ограничимся делением дуги BC рундиста (рисунок 2) на 16 равных частей.

Расчет координат вершин кривой рундиста огранки маркиз

function init_girdle()
{
	// Принимаем ширину рундиста огранки равной 2.
	// Следовательно длина огранки равна lw*2.
	// Поэтому координата Y точки B равна lw.
	// Обозначим эту величину буквой u.
	u = lw;
	if ( u < 0 ) 
		return null;

	// Находим угол наклона касательной к окружности в точке B к оси OY
	// fi = asin(OB/AB) или
	// fi = asin(OB/AC) или 
	// fi = asin(u/(OA + 1)
	// Обозначим s = OA, тогда 
	// fi = asin(u/(s + 1)
	// Так как прямоугольник AOB прямоугольный, то s*s + u*u = (s+1)*(s+1)
	// следовательно s = (u*u - 1)/2 и поэтому:
	fi = Math.asin ( ( u + u ) / ( u * u + 1.0) );
	// Находим угол наклона касательной к эллипсу в точке B к оси OY
	psi = fi + vp;  // δ = vp
	// Находим координату X точки пересечения касательной к эллипсу с осью OX.
	t = u * Math.tan(psi);
	if ( t <= 2.0) 
		return null;
	// Находим величину полуоси эллипса по горизонтали
	a = ( t - 1.0 ) / ( t - 2.0 );
	// Так как ширину рундиста огранки приняли равной 2, то координата X 
	// точки C равна 1. Следовательно величина отрезка O - O1 равна q.
	q = a - 1.0;
	// Находим величину полуоси эллипса по вертикали
	b = u * ( t - 1.0 ) / Math.sqrt( t * t - ( t + t ) );
	
	//  При расчете формы рундиста и получении формул используемых
	// для этого расчета (полуоси эллипса a и b) использовалось свйство касательной к эллипсу.
	// Смотри, напрмер, Н.И.Мусхелишвили "Курс аналитической геометрии" изд.5 § 241.
	// В обозначениях используемых при выводе рундиста на экран это свойство 
	// записывается следующим образом:
	// O1 - координата центра ellipse_1
	// M - координата X пересечения прямой касательной к ellipse_1 в точке B
	// C - координата X пересечения линии ellipse_1 с осью OX
	// a - величина горизонтальной полуоси эллипса ellipse_1			
	/*
	var O = new Point2D(0,0);
	var C = new Point2D(1,0);
	var O1 = new Point2D(C[0] - a, 0);
	var M = new Point2D(t, 0);
	var d1 = O1.Distance(O);
	var d2 = O1.Distance(M);
	var a2 = a * a;  		
	var ratio = (a*a) / ( d1*d2); // ratio = 1 
	*/
	//********************************************************************
	//      Используя введенные ранее обозначения:
	// q * (t + q) = a * a    - Это и есть свойство касательной к эллипсу.
	// Подставив в последнее выражение значение для q = a – 1.0,
	// получим значение для полуоси эллипса a = (t-1)/(t-2).
	// Для расчета величины полуоси эллипса b следут провести вертикальную
	// прямую через центр эллипса O1 и зафиксировать 
	// точку пересечения V этой прямой с касательной к эллипсу.
	// Затем, из рассмотрения подобных треугольников BWV и MOB
	// можно записать пропорцию  p / u = q / t   где p - длина отрезка WV.
	// Отсюда p = u * q / t
	// Исходя из вышеприведенного свойства касательной к эллипсу в точке B
	// можно записать  u * (p + u) = b * b 
	// Теперь зная, как вычисляются величины a, p, u, q, t мы можем записать
	// после некоторых преобразований значение для полуоси b:
	//      b = u * ( t - 1.0 ) / Math.sqrt( t * t - ( t + t ) );
	//************************************************************************
	
	// Расчет сегментов на рундисте.
	gamma = Math.acos ( q / a ); 
	//gamma = Math.atan( u / (a-1) );  - неправильная расстановка вершин
	// В этой программе рундист делится на фиксированные части.
	var delta = gamma/16;

	var i = 0;
	var ang_currrent = 0.0;

	var x, y, w;
	for ( i = 0; i < 17; i++ )
	{
		x = Math.cos(ang_currrent);
		y = -Math.sin(ang_currrent);

		girdle[i] = new Point2D( a * x - q, b * y);
		ang_currrent = ang_currrent + delta;
	}
	
	for ( i = 1; i < 17; i++ )
	{
		girdle[i+16] = new Point2D(-girdle[16-i][0], girdle[16-i][1]);
	}
	
	for ( i = 1; i < 17; i++ )
	{
		girdle[i+32] = new Point2D(girdle[32-i][0], -girdle[32-i][1]);
	}

	for ( i = 1; i < 16; i++ )
	{
		girdle[i+48] = new Point2D(-girdle[48-i][0], girdle[48-i][1]);
	}
}

   Глава 13  ◄     Содержание     ►   Глава 15