|
|
ru.algorithms- RU.ALGORITHMS ---------------------------------------------------------------- From : Oleg Polubasoff 2:5020/400 09 Nov 2001 21:04:28 To : Serg Belyaev Subject : [* - гео] - середина дуги --------------------------------------------------------------------------------
Привет, Серж!
09.11.01 1:26, а также в 13:00 в личном письме, Serg Belyaev писал:
SB> Идея Мусихина использовать ОБЕ диагонали мне понравилась
SB> z=-i*(z2-z1)+(z1+z2) или z=-i*(z2-z1)-(z1+z2) с последующей
SB> нормировкой.
SB> Решение Виталия Мусихина можно чуть улучшить и уменьшить
SB> количество проверок - см. MUS2. Самое главное - уменьшается
SB> количество умножений на 2.
SB> Число умножений можно еще уменьшить на 2 - см. MUS3
SB> procedure mus2(Ax,Ay,Bx,By,Cx,Cy:real);
[чисто паскалевские детали скипнуты]
SB> if (x1*y2-x2*y1)>=0 then begin x:=x1+x2+y2-y1; y:=y1+y2+x1-x2 end
SB> else begin x:=y2-y1-x1-x2; y:=x1-x2-y1-y2 end;
SB> a:=2*(x*x+y*y);
SB> if a>0 then a:=sqrt((x1*x1+y1*y1+x2*x2+y2*y2)/a);
SB> x:=a*x+Cx; y:=a*y+Cy;
Действительно. Очень логичное улучшение. Hадёжность повышается,
а скорость, скорее всего, повышается тоже.
Всё-таки оказалось, что можно обойтись одной проверкой (не считая очень
не лишней проверки перед делением), одной операцией взятия корня и одним
делением.
Кстати, легко показать, что без корня не обойтись. Ведь ответ может
оказаться иррациональным, даже если все исходные данные рациональны.
SB> procedure mus3(Ax,Ay,Bx,By,Cx,Cy:real);
[...]
SB> x:=y2-y1+x1+x2; y:=x1-x2+y1+y2;
SB> A:=y2-y1-x1-x2; B:=x1-x2-y1-y2;
SB> if (abs(x)+abs(y))<(abs(A)+abs(B)) then begin x:=A; y:=B end;
Hад этим условием я некоторое время медитировал. Условие оказалось
корректным.
SB> r:=2*(x*x+y*y);
SB> if r>0 then r:=sqrt((x1*x1+y1*y1+x2*x2+y2*y2)/r);
SB> x:=r*x+Cx; y:=r*y+Cy;
Доведём до логического конца.
// пусть CD - искомое решение
sx = y2-y1; sy = x1-x2; // Cs = CD*2*sin(ACB/2)
cx = x1+x2; cy = y1+y2; // Cc = CD*2*cos(ACB/2)
spcx = sx+cx; spcy = sy+cy; // spc = Cs+Cc
smcx = sx-cx; smcy = sy-cy; // smc = Cs-Cc
spc2 = spcx*spcx + spcy*spcy; // spc^2
smc2 = smcx*smcx + smcy*smcy; // smc^2
x = 0; y = 0;
if (spc2 < smc2) // если 180 < ACB < 360
{ x = smcx; y = smcy; k = smc2; }
else { x = spcx; y = spcy; k = spc2; } // если 0 <= ACB <= 180
// spc2+smc2 = 8*CD^2
if (k>0) k = sqrt((spc2+smc2)/(8*k)); // 0.35 <= k <= 0.5
x *= k; y *= k;
Получилось что-то похожее на бред параноика, но дыр я не вижу. :-)
С уважением, Олег Полубасов.
--- ifmail v.2.15dev5
* Origin: Fidolook Express http://fidolook.da.ru (2:5020/400)
Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.algorithms/6577d14f9dec.html, оценка из 5, голосов 10
|