В данном приложении содержатся процедуры V_Plclip, реализующие простой алгоритм отсечения произвольного многоугольника по выпуклому многоугольному окну отсечения и тестовая программа проверки их работы.
Процедуры реализуют алгоритм, который, как и алгоритм Сазерленда-Ходгмана, последовательно отсекает весь многоугольник по каждому из ребер окна отсечения.
/*=================================================== V_PLCLIP * Файл V_PLCLIP.C - процедуры простого алгоритма отсечния * многоугольника * Последняя редакция: * 25.12.93 17:25 */ #include <graphics.h> #include "V_WINDOW.C" /* Глобалы и проц работы с окнами */ /* Включаемый файл V_WINDOW.C содержит * подрограммы и глобалы для окон: * * V_SetPclip - установить размеры многоугольного окна * отсечения * V_GetPclip - опросить параметры многоугольного окна * отсечения * V_SetRclip - установить размеры прямоугольного окна * отсечения * V_GetRclip - опросить размеры прямоугольного окна * отсечения * * Глобальные скаляры для алгоритмов отсечения по * прямоугольному окну - Коэна-Сазерленда, Fc-алгоритм, * Лианга-Барски * * static float Wxlef= 100.0, -- Координаты левого нижнего и * Wybot= 100.0, -- правого верхнего углов окна * Wxrig= 300.0, -- отсечения * Wytop= 200.0; * * Глобальные скаляры для алгоритма Кируса-Бека * отсечения по многоугольному окну * * Координаты прямоугольного окна * static float Wxrect[4]= {100.0, 100.0, 300.0, 300.0 }; * static float Wyrect[4]= {100.0, 200.0, 200.0, 100.0 }; * * Перепендикуляры к сторонам прямоугольного окна * static float WxNrec[4]= {1.0, 0.0, -1.0, 0.0 }; * static float WyNrec[4]= {0.0, -1.0, 0.0, 1.0 }; * * Данные для многоугольного окна * static int Windn=4; -- Кол-во вершин у окна * static float *Windx= Wxrect, -- Координаты вершин окна * *Windy= Wyrect; * static float *Wnormx= WxNrec, -- Координаты нормалей * *Wnormy= WyNrec; */
/*-------------------------------------------------- Pl_clip0 * Служебная процедура, отсекает многоугольник * относительно одного ребра окна * * Отсечение выполняется в цикле по сторонам многоугольника * При первом входе в цикл только вычисляются величины для * начальной точки: координаты, скалярное произведение, * определяющее ее расположение относительно ребра окна, и * код расположения. * При последующих входах в цикл эти значения вычисляются * для очередной вершины. * По значениям кодов расположения вершин для стороны * многоугольника определяется как она расположена * относительно ребра и вычисляются координаты результирующего * многоугольника. */ static int Pl_clip0 (N_reb, N_in, X_in, Y_in, X_ou, Y_ou) int N_reb, N_in; float *X_in, *Y_in, *X_ou, *Y_ou; { int ii, jj; int pozb, /* Коды расположения начальной точки */ pozn, /* многоугольника и точек тек стороны */ pozk; /* 0/1/2 - пред точка вне/на/внутри */ float Rx,Ry; /* Координаты начала ребра окна */ float Nx, Ny; /* Нормаль к ребру окна */ float xb, yb; /* Начальная точка многоугольника */ float xn, yn; /* Начальная точка текущей стороны */ float xk, yk; /* Конечная точка текущей стороны */ float t; /* Значение параметра точки пересечения */ float Qb,Qn,Qk; /* Скалярные произведения */ float *ptx_ou; /* Запрос параметров ребра окна */ Rx= Windx[N_reb]; Ry= Windy[N_reb]; Nx= Wnormx[N_reb]; Ny= Wnormy[N_reb]; /* Цикл отсчения многоугольника ребром окна */ ii= 0; ++N_in; ptx_ou= X_ou; while (--N_in >= 0) { if (N_in) { xk= *X_in++; yk= *Y_in++; /* Кон точка стороны */ Qk= (xk-Rx)*Nx + (yk-Ry)*Ny; /* Параметр положения */ pozk= 1; /* 1 - точка на гр. */ if (Qk < 0) --pozk; else /* 0 - точка вне */ if (Qk > 0) ++pozk; /* 2 - точка внутри */ } else { xk= xb; yk= yb; Qk= Qb; pozk= pozb; } if (!ii) { xb= xn= xk; yb= yn= yk; Qb= Qn= Qk; pozb= pozn= pozk; ++ii; continue; } jj= 0; switch (pozn*3 + pozk) { /* Стар Нов Выход */ case 0: goto no_point; /* вне-вне нет */ case 1: goto endpoint; /* вне-на конечная */ case 2: goto intersec; /* вне-вну перес,кон */ case 3: goto no_point; /* на -вне нет */ case 4: /* на -на конечная */ case 5: goto endpoint; /* на -вну конечная */ case 6: goto no_end; /* вну-вне пересечен */ case 7: /* вну-на конечная */ case 8: goto endpoint; /* вну-вну конечная */ } no_end: ++jj; intersec: t= Qn/(Qn-Qk); *X_ou++= xn + t*(xk-xn); *Y_ou++= yn + t*(yk-yn); if (!jj) { endpoint: *X_ou++= xk; *Y_ou++= yk; } no_point: xn= xk; yn= yk; Qn= Qk; pozn= pozk; } return (X_ou - ptx_ou); } /* Pl_clip0 */
/*--------------------------------------------------- V_Plclip * Простая процедура отсечения многоугольника * N_in - число вершин во входном многоугольнике * X_in, Y_in - координаты вершин отсекаемого мног-ка * этот массив будет испорчен * Возвращает: * < 0 - ошибки * >= 0 - количество вершин в выходном многоугольнике * X_ou, Y_ou - координаты вершин отсеченного многоугольника */ int V_Plclip (N_in, X_in, Y_in, X_ou, Y_ou) int N_in; float *X_in, *Y_in, *X_ou, *Y_ou; { int ii, N_ou; float *ptr; if ((N_ou= N_in) < 3) {N_ou= -1; goto all; } if (Windn < 3) {N_ou= -2; goto all; } for (ii=0; ii<Windn; ++ii) { N_ou= Pl_clip0 (ii, N_ou, X_in, Y_in, X_ou, Y_ou); ptr= X_in; X_in= X_ou; X_ou= ptr; ptr= Y_in; Y_in= Y_ou; Y_ou= ptr; } if (!(Windn & 1)) { ii= N_ou; while (--ii >= 0) {*X_ou++= *X_in++; *Y_ou++= *Y_in++; } } all: return N_ou; } /* V_Plclip */
/*=================================================== T_PLCLIP * ТЕСТ процедуры V_Plclip для отсечения многоугольника * * При первом входе устанавливается восьмиугольное окно * отсечения: * X: 150, 100, 100, 150, 250, 300, 300, 250 * Y: 100, 150, 250, 300, 300, 250, 150, 100 * * И на нем отсекается треугольник: * (10,160),(90,220),(170,160) * * Затем выдается запрос на количество вершин в * новом отсекаемом многоугольнике: * --- Vertexs in polyline= XX ? * При вводе числа > 0 будут запрашиваться координаты вершин * много-ка и выполняться его отсечение * При вводе числа = 0 программа затребует ввод координат * нового прямоугольного окна отсечения * При вводе числа < 0 программа запросит переустановку * многоугольного окна отсечения: * * ----Vertexs in clip window= XX ? * При вводе числа > 0 будут запрашиваться координаты вершин. * При вводе числа = 0 программа затребует ввод координат * прямоугольного окна. * При вводе числа < 0 программа закончится. */
#include <graphics.h> #include "V_PLCLIP.C" /*--------------------------------------------------- DrawPoly * Чертит контур многоугольника */ void DrawPoly (col, n, x, y) int col, n; float *x, *y; { int ii, jj; setcolor (col); for (ii=0; ii<n; ++ii) { if ((jj= ii+1) >= n) jj= 0; line (x[ii], y[ii], x[jj], y[jj]); } } /* DrawPoly */ /*---------------------------------------------------- CLR_STR * Зачищает строку выводом в нее пробелов */ void CLR_STR (void) { printf (" \r"); } /*------------------------------------------------ PLCLIP_MAIN */ void main (void) { int ii, jj, fon; /* Индекс фона */ float Wxn,Wyn, /* Прямоугольный отсекатель */ Wxk,Wyk; int N_wind= 0; /* Вводимый отсекатель */ float X_wind[100], Y_wind[100]; float X_norm[100], Y_norm[100]; int wnum; /* Запрошенный отсекатель */ float *wx,*wy,*wnx,*wny; int N_poly= 0; /* Отсекаемый многугольник */ float X_poly[100], Y_poly[100]; int N_clip= 0; /* Отсеченный многугольник */ float X_clip[100], Y_clip[100]; int entry= 0; /* 0/1 - нет/был вывод по умолчанию */ int gdriver= DETECT, gmode; initgraph (&gdriver, &gmode, ""); fon= 0; /* Цвет фона */ setbkcolor(fon); /* Очистка экрана */ cleardevice(); /*--------------- Установить окно отсечения ----------------*/ new_window: gotoxy (1,1); if (!entry) { N_wind= 8; wx= X_wind; wy= Y_wind; *wx++= 150; *wx++= 100; *wx++= 100; *wx++= 150; *wy++= 100; *wy++= 150; *wy++= 250; *wy++= 300; *wx++= 250; *wx++= 300; *wx++= 300; *wx++= 250; *wy++= 300; *wy++= 250; *wy++= 150; *wy++= 100; goto wr_window; } if (!N_poly) goto set_rect;
/*---------- Задание многоугольного окна отсечения ---------*/ set_window: CLR_STR (); printf ("----Vertexs in clip window= %d ? ", N_wind); scanf ("%d", &N_wind); if (N_wind < 0) goto all; if (!N_wind) goto set_rect; for (ii=0; ii<N_wind; ++ii) { CLR_STR (); printf ("X_wind[%d], Y_wind[%d] ? ", ii, ii); scanf ("%f%f", &X_wind[ii], &Y_wind[ii]); } wr_window: jj= V_SetPclip (N_wind, X_wind, Y_wind, X_norm, Y_norm); if (jj) { printf ("Error=%d in polyline window\n", jj); goto set_window; } else goto ou_win;
/*---------- Задание прямоугольного окна отсечения ---------*/ set_rect: V_GetRclip (&Wxn, &Wyn, &Wxk, &Wyk); get_rect: CLR_STR (); printf ("Rect window: (Xn=%f Yn=%f Xk=%f Yk=%f) ? ", Wxn, Wyn, Wxk, Wyk); scanf ("%f%f%f%f", &Wxn, &Wyn, &Wxk, &Wyk); wr_rect: jj= V_SetRclip (Wxn, Wyn, Wxk, Wyk); if (jj) { printf ("Error=%d in rectangle window\n", jj); goto get_rect; }
/*--------------- Прорисовка окна отсечения ----------------*/ ou_win: wnum= V_GetPclip (&wx, &wy, &wnx, &wny); DrawPoly (LIGHTRED, wnum, wx, wy);
/*------- Ввод координат отсекаемого многоугольника --------*/ set_poly: gotoxy (1,1); if (!entry) { /* При первом входе отрисовка по умолчанию */ N_poly= 3; X_poly[0]= 10; X_poly[1]= 90; X_poly[2]= 170; Y_poly[0]= 160; Y_poly[1]= 220; Y_poly[2]= 160; } else { CLR_STR (); printf ("--- Vertexs in polyline= %d ? ",N_poly); scanf ("%d", &N_poly); if (N_poly <= 0) goto new_window; for (ii=0; ii<N_poly; ++ii) { printf (" \r"); printf ("X_poly[%d], Y_poly[%d] ? ", ii, ii); scanf ("%f%f", &X_poly[ii], &Y_poly[ii]); } } ++entry; /*---------- Прорисовка отсекателя и отсекаемого -----------*/ wnum= V_GetPclip (&wx, &wy, &wnx, &wny); DrawPoly (LIGHTRED, wnum, wx, wy); DrawPoly (LIGHTGREEN, N_poly, X_poly, Y_poly); /*----------------------- Отсечение ------------------------*/ N_clip= V_Plclip(N_poly, X_poly, Y_poly, X_clip, Y_clip); /*----------------- Прорисовка отсеченного -----------------*/ DrawPoly (YELLOW, N_clip, X_clip, Y_clip); goto set_poly; all: closegraph(); } /* PLCLIP_MAIN */
1 Переход к модели с перечислением занятых точек также возможен из любой другой, но при решении проблем точности аппроксимации.
Релятивисты и позитивисты утверждают, что "мысленный эксперимент" весьма полезный интрумент для проверки теорий (также возникающих в нашем уме) на непротиворечивость. В этом они обманывают людей, так как любая проверка может осуществляться только независимым от объекта проверки источником. Сам заявитель гипотезы не может быть проверкой своего же заявления, так как причина самого этого заявления есть отсутствие видимых для заявителя противоречий в заявлении.
Это мы видим на примере СТО и ОТО, превратившихся в своеобразный вид религии, управляющей наукой и общественным мнением. Никакое количество фактов, противоречащих им, не может преодолеть формулу Эйнштейна: "Если факт не соответствует теории - измените факт" (В другом варианте " - Факт не соответствует теории? - Тем хуже для факта").
Максимально, на что может претендовать "мысленный эксперимент" - это только на внутреннюю непротиворечивость гипотезы в рамках собственной, часто отнюдь не истинной логики заявителя. Соответсвие практике это не проверяет. Настоящая проверка может состояться только в действительном физическом эксперименте.
Эксперимент на то и эксперимент, что он есть не изощрение мысли, а проверка мысли. Непротиворечивая внутри себя мысль не может сама себя проверить. Это доказано Куртом Гёделем.
Понятие "мысленный эксперимент" придумано специально спекулянтами - релятивистами для шулерской подмены реальной проверки мысли на практике (эксперимента) своим "честным словом". Подробнее читайте в FAQ по эфирной физике.
|
![]() |