Глава 24  ◄     Содержание     ►   Глава 26

Three.js и геометрия.   Глава 25.   Построение рундиста огранки имеющей рундист в форме "подушки" (cushion). часть 3

Иногда желательно при изменении размеров площадки огранки соответствующим образом менять размеры сегментов рундиста. При таком подходе к построению огранки она зачастую приобретает более красивый вид чем при независмом делении рундиста на сегменты. По приведенной online-программе можно проследить взаимосвязь короны и рундиста огранки.

No      All      Cr-Gd-Pav

При способе построения этой огранки, который мы будем использовать, при изменении удлинения огранки вид рундиста и короны должен меняться таким образом, чтобы форма граней C и B оставалась неизменной, а грань A растягивалась или сжималась вдоль оси OX соответственно с изменением значения удлинения огранки. Для того чтобы выполнить указанное требование построение короны и рундиста огранки должно производиться одновременно – так как их внешний вид является взаимозависимым. Форма огранки при трех различных значениях параметра Girdle ratio показана на рисунке 1.

На рисунке 2 показаны геометрические построения, используемые при расстановке вершин на рундисте и короне. Построение начинается с расчета формы рундиста, которое осуществляется точно таким же образом, как это было сделано в предыдущей главе. Однако расстановка вершин на рундисте делается совершенно иначе.

Первое, что мы для этого сделаем – это построим вспомогательную окружность cir4. Эта окружность поможет найти размеры угловых сегментов рундиста. Определим сначала положение центра O4 этой окружности. Координаты центра окружности O4 являются одновременно координатами x и y вершины рундиста 8. При определении значения радиуса окружности cir4 используется значение параметра dr, которому в СДМ соответствует поле dr. Этот параметр можно использовать для изменения относительных размеров сегментов рундиста.

Зная координаты точек P1, P2, O4, а также значения координат вершин 0 и 1 короны, можно составить уравнения плоскостей, в которых лежат главные четырехугольные грани короны A, B и C. Уравнения этих плоскостей создаются по трем принадлежащим им точкам. Ниже приведена та часть исходного кода функции InitGirdle, в которой находятся уравнения плоскостей, в которых лежат грани A, B и C короны. При нахождении уравнений учитываем, что высота короны h_crown равна величине
   h_crown = tan(угол_короны) ∙ (1 – ширина_площадки) / 2
Следующим шагом является определение уравнения линии пересечения плоскостей – с одной стороны плоскостей граней A и C, а с другой стороны – граней B и C. На рисунке 2 эти линии обозначены как line_AC и line_BC соответственно.

	// Главные четырехугольные грани короны
	// Конструируем плоскость в которой лежит грань A
	var planeA = new Plane3D();
	planeA.CreatePlaneThreePoints(crown[0],
	                              new Point3D(0, 0.5, r/2),
	                              new Point3D(P1[0], P1[1], h_crown + r/2));

	// Конструируем плоскость в которой лежит грань B
	var planeB = new Plane3D();
	planeB.CreatePlaneThreePoints(crown[2],
	                              new Point3D(lw/2, 0.0, r/2),
	                              new Point3D(P2[0], P2[1], h_crown + r/2));

	// Конструируем плоскость в которой лежит грань C
	var planeC = new Plane3D();
	planeC.CreatePlaneThreePoints(new Point3D(P1[0], P1[1], h_crown + r/2),
	                              new Point3D(P2[0], P2[1], h_crown + r/2),
	                              new Point3D(O4[0], O4[1], r/2));	
	
	// Конструируем линию пересечения плоскостей A и C
	var vector = planeA.VectorIntersectionTwoPlanes(planeC);
	var vector_AC = new Vector2D(vector[0], vector[1]);
	vector_AC.Normer();	
	var line_AC = new Line2D();
	line_AC.CreateLineVectorPoint(vector_AC, P1);
	
	// Конструируем линию пересечения плоскостей B и C
	vector = planeB.VectorIntersectionTwoPlanes(planeC);
	var vector_BC = new Vector2D(vector[0], vector[1]);
	vector_BC.Normer();
	var line_BC = new Line2D();
	line_BC.CreateLineVectorPoint(vector_BC, P2);	
	

Далее поступим следующим образом – введем параметр огранки, которому дадим название ratio. В СДМ этому параметру соответствует одноименное поле ratio. Рассмотрим отрезок соединяющий точки P0 и O4. Будем рассматривать значение ratio как отношение, в котором оно делит длину отрезка P0 - O4. В результате этого деления получаются два отрезка – P0 - P4 и P4 - O4. Иными словами значение ratio задает положение точки P4 на отрезке P0 - O4. Проведем еще одну прямую – line_P4. Она должна проходить через точку P4 и быть параллельной прямой, проходящей через ранее найденные точки P1 и P2. Следом за этим найдем точки A и B пересечения прямой line_P4 с проекциями на горизонтальную плоскость прямых line_AC и line_BC. Так как эти точки лежат на проекциях прямых line_AC и line_BC то поэтому их и обозначили как A и B. Напомним, что по этим прямым пересекаются плоскости, в которых лежат грани короны A, B и C. Найденные точки A и B будем рассматривать как проекции вершин короны 8 и 9 на горизонтальную плоскость OXY. Для нахождения высоты, на которой расположены сами трехмерные точки имеющие проекции A и B, проведем через A и B прямые перпендикулярные к плоскости OXY. Точки пересечения этих прямых с плоскостями, в которых лежат грани короны A и B и определят координаты по оси OZ вершин короны 8 и 9. Следовательно, значение параметра ratio определяет положение вершин короны 8 и 9. Таким образом, мы рассчитали координаты всех вершин короны для одной четверти огранки. Это вершины обозначены числами 0, 1, 2, 8 и 9. Нажав в online-программе переключатель Cr-Gd-Par можно увидеть нумерацию вершин короны (вершины короны отобразятся красным цветом).

	// Точка P4 может двигаться по прямой между точками P0 и O4
	var P4 = new Point2D();
	P4[0] = P0[0] * ratio + (1 - ratio) * O4[0];
	P4[1] = P0[1] * ratio + (1 - ratio) * O4[1];
	// Прямая параллельная прямой P1 - P2 и проходящая через точку P4
	var line_P4 = new Line2D();
	line_P4.CreateLineVectorPoint(new Vector2D(P1[0] - P2[0], P1[1] - P2[1]), P4);
	
	//   Находим точки пересечения найденной только что прямой line_P4
	// с проекциями линий пересечения плоскостей line_AC и line_BC
	var A = line_AC.IntersectionTwoLines(line_P4); 
	var B = line_BC.IntersectionTwoLines(line_P4); 
	
	// Конструируем вершины звезды короны
	var Z1 = new Vector3D(0,0,1); // Вертикально направленный единичный вектор

	var lineVert_A = new Line3D(); // Вертикальная прямая проходящая через точку A
	lineVert_A.CreateLineVectorPoint(Z1, new Point3D(A[0], A[1], 0));
	crown[8] = lineVert_A.IntersectionLinePlane(planeA);

	var lineVert_B = new Line3D(); // Вертикальная прямая проходящая через точку B
	lineVert_B.CreateLineVectorPoint(Z1, new Point3D(B[0], B[1], 0));
	crown[9] = lineVert_B.IntersectionLinePlane(planeB);

Определим координаты точек S и V лежащих на границах угловых сегментов рундиста огранки. Для этого проводим одну прямую проходящую через точки O1 и A, а другую прямую – через точки O2 и B. Точки пересечения этих прямых с линией рундиста определят граничные точки угловых сегментов. Координаты x и y точки S соответствует координатам вершины рундиста 4 в горизонтальной плоскости, а координаты x и y точки V соответствует координатам вершины рундиста 12 в горизонтальной плоскости. Таким образом, нами определены координаты всех узловых вершин рундиста 0, 4, 8, 12 и 16 для одной его четверти. Перед этим мы уже нашли координаты вершин 0, 1, 2, 8 и 9 короны. Координаты остальных узловых вершин рундиста и координаты остальных вершин короны можно найти исходя из соображений симметрии огранки относительно плоскостей OXZ и OYZ. Дальнейшие действия по делению каждого из полученных сегментов рундиста на четыре части подобны уже рассмотренным действиям при построении предыдущего рундиста огранки "подушка".

	// Вычисляем вершины рундиста со стороны короны
	// Прежде всего вычисляем координаты узловых вершин рундиста 
	girdle[0] = new Point3D();
	girdle[0][0] = 0;
	girdle[0][1] = 0.5;
	girdle[0][2] = r/2;
	
	// Точки s и v определяют границу сегментов рундиста
	// Точки лежащие на границе сегментов seg1 и seg2
	              // и также на границе сегментов seg3 и seg4

	// Уравнение прямой проходящей через центр большей окружности O1 и точку A
	var line_O1_A = new Line2D(O1, A);

	if(!cir1.IntersectionLineCircle(line_O1_A, point1, point2))
	{
		return null;
	}
	var s = new Point2D()
	if (point1[1] > point2[1])
	{
		s[0] = point1[0]; s[1] = point1[1];
	}
	else
	{
		s[0] = point2[0]; s[1] = point2[1];			
	}	

	girdle[4] = new Point3D();
	girdle[4][0] = s[0];
	girdle[4][1] = s[1];
	girdle[4][2] = r/2;
	
	girdle[8] = new Point3D();
	girdle[8][0] = O4[0];
	girdle[8][1] = O4[1];
	girdle[8][2] = r/2;

	// Уравнение прямой проходящей через центр меньшей окружности O2 и точку B
	var line_O2_B = new Line2D(O2, B);

	if(!cir2.IntersectionLineCircle(line_O2_B, point1, point2))
	{
		return null;
	}
	var v = new Point2D()
	if (point1[0] > point2[0])
	{
		v[0] = point1[0]; v[1] = point1[1];
	}
	else
	{
		v[0] = point2[0]; v[1] = point2[1];			
	}

	girdle[12] = new Point3D();
	girdle[12][0] = v[0];
	girdle[12][1] = v[1];
	girdle[12][2] = r/2;

	girdle[16] = new Point3D();
	girdle[16][0] = lw/2;
	girdle[16][1] = 0;
	girdle[16][2] = r/2;

Единственное отличие заключается в том, что, так как положение вершин короны уже определено, нам следует найти значения координаты z каждой вершины огранки со стороны короны (раньше при расчете рундиста других моделей огранок, до его корректировки по высоте, мы полагали его равным значению толщина_рундиста/2). Для нахождения этих координат мы строим плоскости, в которых лежат грани короны, примыкающие к рундисту, и протыкаем каждую такую плоскость вертикальными прямыми, исходящими из найденных точек проекций вершин рундиста на горизонтальную плоскость. Высота, на которой происходит протыкание, определит координату z соответствующей вершины рундиста лежащей между его узловыми вершинами. Таким образом корректировка вершин рундиста по высоте со стороны короны входит непосредственно и изначально в расчет рундиста. Для узловых вершин рундиста высота, на которой они расположены, равна значению толщина_рундиста/2.

   Глава 24  ◄     Содержание     Глава 26