СОВЕТ 144. Для тех, кто занимается геометрическими расчетами

Для них, возможно, пригодятся две процедуры, которые приведены в модуле XY_TESTC.BAS (листинг 1). Они сохранились у нас еще со времен Basic/DOS, поэтому их текст и имеет такой вид (например, все ключевые слова записаны прописными буквами). Процедура CircleTestXY определяет местоположение точки относительно фигуры-многоугольника (внутри или снаружи), CircleSquare вычисляет площадь многоугольника. Следует обратить внимание на то, что одна из вершин многоугольника задана в массиве дважды в качестве начальной и конечной точки.

КСТАТИ. Раньше названия языков программирования и их ключевых слов было принято писать прописными буквами. Однако в начале 90-х годов Международная Организация по Стандартам (ISO — International Standard Organization) приняла решение об изменении этого правила и с тех пор они пишутся так: первая буква — прописная, остальные — строчные.

ЛИСТИНГ 1.

DECLARE SUB CircleTestXY (xyd!(), Np%, x0!, y0!, kz%)
DECLARE SUB CircleSquare (xyd!(), Np%, Square!)
DEFINT I-N
'*****************************************************
'         Модуль XY_TESTC.BAS
'
' Процедуры:
'   CircleTestXY - определение местоположения точки относительно
'                  фигуры-многоугольника
'   CircleSquare - вычисление площади многоугольника
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
   ' тестовый пример использования функций
   Np = 6: DIM xyd(Np, 2)      ' массив для пятиугольника
   xyp(1, 1) = 10: xyp(2, 1) = 20
   xyp(1, 2) = 0: xyp(2, 2) = 10
   xyp(1, 3) = -10: xyp(2, 3) = 20
   xyp(1, 4) = -10: xyp(2, 4) = -20
   xyp(1, 5) = 10: xyp(2, 5) = -20
   xyp(1, Np) = xyp(1, 1): xyp(2, Np) = xyp(2, 1)
   ' вычисление площади многоугольника
   CALL CircleSquare(xyp(), Np, Square)
   ' проверка того, где находится заданная точка
   x0 = 0: y0 = 0   ' координаты тестируемой точки
   CALL CircleTestXY(xyp(), Np, x0, y0, kz)
   PRINT "kz, Square = "; kz; Square
END

SUB CircleSquare (xyd(), Np, Square)
'    Вычисление площади многоугольника
'———————————————————-
' ВХОД:
'  xyd() - массив координат углов многоугольника
'    x = xyd(1,i), y = xyd(2,i) ; i = 1 to Np
'  (Np-1) - количество узлов
'  координаты 1-й точки = координатам N-й
'
' ВЫХОД: Square - площадь многоугольника
'''''''''''''''''''''''''''''''''''''''''''''''
     CONST pi = 3.141593
     Square = 0
     FOR k = 1 TO Np     ' Np + 1
       x2 = xyd(1, k): y2 = xyd(2, k)
       v2 = SQR(x2 * x2 + y2 * y2)
       ay2 = ABS(y2): ax2 = ABS(x2)
       IF ax2 * 10000 > ay2 THEN
         alfa2 = ATN(ay2 / ax2)
       ELSE alfa2 = pi * .5
       END IF
       IF x2 < 0 THEN alfa2 = pi - alfa2
       IF y2 < 0 THEN alfa2 = -alfa2
       IF k > 1 THEN   ' проверка перехода
         Square = Square + .5 * SIN(alfa2 - alfa1) * v1 * v2
       END IF
       x1 = x2: y1 = y2: v1 = v2: alfa1 = alfa2
     NEXT
END SUB

SUB CircleTestXY (xyd(), Np, x0, y0, kz)
'
'    Проверка местонахождения точки на плоскости
'    относительно многоугольника - внутри или cнаружи
'——————————————————————————-
' ВХОД:
'  xyd() - массив координат углов многоугольника
'    x = xyd(1,i), y = xyd(2,i) ; i = 1 to Np
'    (Np-1) - количество узлов
'    координаты 1-й точки = координатам N-й
'  x0,y0  - координаты тестируемой точки
'
' ВЫХОД:  положение тестируемой точки
'        kz = 0  - вне
'           = -100 - на границе
'           = -4   - внутри (обход по часовой стрелке)
'           =  4   - внутри (против часовой стрелки)
'''''''''''''''''''''''''''''''''''''''''''''''
     kz = 0
     FOR k = 1 TO Np   ' Np + 1
                       ' IF l > Np THEN k = 1 ELSE k = l
       x2 = xyd(1, k) - x0: y2 = xyd(2, k) - y0
       '
       ' проверка четверти плоскости
       kv2 = 0
       IF x2 >= 0 AND y2 > 0 THEN kv2 = 1
       IF x2 < 0 AND y2 >= 0 THEN kv2 = 2
       IF x2 <= 0 AND y2 < 0 THEN kv2 = 3
       IF x2 > 0 AND y2 <= 0 THEN kv2 = 4
       IF kv2 = 0 THEN kz = -100: EXIT FOR
       '
       IF k > 1 THEN   ' проверка перехода
         IF kv2 <> kv1 THEN   ' переход в другую четверть
           kv = kv2 - kv1
           IF kv = 3 THEN kv = -1
           IF kv = -3 THEN kv = 1
           IF kv = 2 OR kv = -2 THEN   ' переход через две четверти
             IF x1 = x2 THEN kz = -100: EXIT FOR
             yb = (y2 * x1 - y1 * x2) / (x1 - x2)
             IF yb = 0 THEN kz = -100: EXIT FOR
             kv = kv * SGN(yb)
             IF kv1 = 2 OR kv1 = 4 THEN kv = -kv
           END IF
           kz = kz + kv
         END IF
       END IF
       x1 = x2: y1 = y2: kv1 = kv2
     NEXT
END SUB

В начало статьи