Построение рядов плиток
Создание плиток
|
| ||||
Построение рядов плиток |
| ||||
Попробуем разобраться со следующей функцией. Для этого сравним ее с описанным алгоритмом и найдем упомянутые выше геометрические величины. Здесь может встретиться несколько новых функций AutoLISP. Подробнее об этих функциях см. электронный документ AutoLISP Reference. Теперь ознакомимся с кодом (но пока не надо добавлять его в файл).
(defun gp:Calculate-and-Draw-Tiles (BoundaryData / PathLength TileSpace TileRadius SpaceFilled SpaceToFill RowSpacing offsetFromCenter rowStartPoint pathWidth pathAngle ObjectCreationStyle TileList) (setq PathLength (cdr (assoc 41 BoundaryData)) TileSpace (cdr (assoc 43 BoundaryData)) TileRadius (cdr (assoc 42 BoundaryData)) SpaceToFill (- PathLength TileRadius) RowSpacing (* (+ TileSpace (* TileRadius 2.0)) (sin (Degrees->Radians 60)) ) ;_ end of * SpaceFilled RowSpacing offsetFromCenter 0.0 offsetDistance (/ (+ (* TileRadius 2.0) TileSpace) 2.0) rowStartPoint (cdr (assoc 10 BoundaryData)) pathWidth (cdr (assoc 40 BoundaryData)) pathAngle (cdr (assoc 50 BoundaryData)) ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData))) ) ;_ end of setq ;; Compensate for the first call to gp:calculate-Draw-tile Row ;; in the loop below. (setq rowStartPoint (polar rowStartPoint (+ pathAngle pi) (/ TileRadius 2.0) ) ;_ end of polar ) ;_ end of setq ;; Draw each row of tiles. (while (<= SpaceFilled SpaceToFill) ;; Get the list of tiles created, adding them to our list. (setq tileList (append tileList (gp:calculate-Draw-TileRow (setq rowStartPoint (polar rowStartPoint pathAngle RowSpacing ) ;_ end of polar ) ;_ end of setq TileRadius TileSpace pathWidth pathAngle offsetFromCenter ObjectCreationStyle ) ;_ end of gp:calculate-Draw-TileRow ) ;_ end of append ;; Calculate the distance along the path for the next row. SpaceFilled (+ SpaceFilled RowSpacing) ;; Alternate between a zero and a positive offset ;; (causes alternate rows to be indented). offsetFromCenter (if (= offsetFromCenter 0.0) offsetDistance 0.0 ) ;_ end of if ) ;_ end of setq );_ end of while ;; Return the list of tiles created. tileList ) ;_ end of defun Некоторые участки кода требуют дополнительных пояснений. Следующий фрагмент располагается непосредственно перед началом цикла while: ;; Compensate for the very first start point!! (setq rowStartPoint(polar rowStartPoint (+ pathAngle pi)(/ TileRadius 2.0))) Здесь необходимо пояснить следующее: (setq rowStartPoint(polar rowStartPoint pathAngle RowSpacing)) Иначе говоря, в момент вызова функции gp:calculate-Draw-TileRow точка rowStartPoint переносится на расстояние RowSpacing от текущего положения rowStartPoint. Для того чтобы компенсировать начальный сдвиг вперед rowStartPoint при рисовании первого ряда (т.е. при первом выполнении цикла while), необходимо слегка передвинуть rowStartPoint в обратном направлении. Благодаря этому удается избежать образования слишком большого пустого пространства между границей дорожки и первым рядом. Точку достаточно сдвинуть на расстояние, равное половине радиуса плитки (TileRadius). Этого можно достичь, используя функцию polar для перемещения точки rowStartPoint вдоль вектора, повернутого на 180 градусов относительно угла PathAngle. При этом точка временно оказывается за пределами границы дорожки. Следующий фрагмент (слегка измененный для упрощения чтения) также может вызвать затруднения: (setq tileList (append tileList (gp:calculate-Draw-TileRow (setq rowStartPoint (polar rowStartPoint pathAngle RowSpacing) ) ;_ end of setq TileRadius TileSpace pathWidth pathAngle offsetFromCenter ObjectCreationStyle ))) По сути, он представляет собой вызов функции gp:calculate-Draw-TileRow, вложенный в функцию append, которая, в свою очередь, вложена в функцию setq. Функция gp:calculate-Draw- TileRow возвращает идентификаторы объектов для построенных плиток. Такими идентификаторами обозначается каждая плитка на рисунке. Плитки строятся ряд за рядом, поэтому функция возвращает идентификаторы объектов сразу для целого ряда. Функция append добавляет их в список tileList. Ближе к концу функции можно обнаружить следующий фрагмент кода: (setq offsetFromCenter (if (= offsetFromCenter 0.0) offsetDistance 0.0 ) ) Этот фрагмент отвечает за рисование рядов плиток в шахматном порядке. Здесь происходит либо совмещение центра средней плитки с центральной линией дорожки, либо сдвиг плиток относительно этой линии. Алгоритм выглядит следующим образом: Установить сдвиг равным следующему: Если текущий сдвиг равен 0, установить его равным расстоянию сдвига; Иначе, установить сдвиг равным 0. |