Нарисуйте простой робот в C#
Это действительно упражнение в использовании графических преобразований. Вы можете нарисовать каждый сегмент и суставы в руке, используя простые методы рисования и преобразования для поворота и перевода частей в правильное положение.
Основная идея состоит в том, чтобы рассматривать этапы руки один за другим и использовать преобразования для перехода от одного к другому.
Предположим, что три сегмента плеча имеют длины L1, L2 и L3, а углы поворота на трех стыках - A1, A2 и A3.
Первый шарнир поворачивает рычаг на угол A1 на фиксированном плече. Второе соединение переведено на расстояние L1 в направлении первого сегмента руки.
Второй шарнир поворачивает рычаг на угол A2 на «локте». Третий шарнир сдвинут расстояние L2 в направлении второго сегмента руки.
Третий шарнир поворачивает рычаг на угол A3 на «запястье». Конец рычага переведен на расстояние L3 в направлении третьего сегмента руки.
Эта программа использует следующий код для рисования руки робота.
private void DrawRobotArm(Graphics gr) { const int UpperArmLength = 75; const int LowerArmLength = 50; const int WristLength = 20; gr.SmoothingMode = SmoothingMode.AntiAlias; gr.Clear(picCanvas.BackColor); float cx = picCanvas.ClientSize.Width / 2; float cy = picCanvas.ClientSize.Height / 2; gr.TranslateTransform(cx, cy); GraphicsState initial_state = gr.Save(); Rectangle rect = new Rectangle(0, -2, 100, 5); gr.RotateTransform(-scrJoint1.Value, MatrixOrder.Prepend); rect.Width = UpperArmLength; gr.FillRectangle(Brushes.LightBlue, rect); gr.DrawRectangle(Pens.Blue, rect); gr.TranslateTransform(UpperArmLength, 0, MatrixOrder.Prepend); gr.RotateTransform(-scrJoint2.Value, MatrixOrder.Prepend); rect.Width = LowerArmLength; gr.FillRectangle(Brushes.LightBlue, rect); gr.DrawRectangle(Pens.Blue, rect); gr.TranslateTransform(LowerArmLength, 0, MatrixOrder.Prepend); gr.RotateTransform(-scrJoint3.Value, MatrixOrder.Prepend); rect.Width = WristLength; gr.FillRectangle(Brushes.LightBlue, rect); gr.DrawRectangle(Pens.Blue, rect); gr.Restore(initial_state); Rectangle joint_rect = new Rectangle(-4, -4, 9, 9); gr.FillEllipse(Brushes.Red, joint_rect); gr.RotateTransform(-scrJoint1.Value, MatrixOrder.Prepend); gr.TranslateTransform(UpperArmLength, 0, MatrixOrder.Prepend); gr.FillEllipse(Brushes.Red, joint_rect); gr.RotateTransform(-scrJoint2.Value, MatrixOrder.Prepend); gr.TranslateTransform(LowerArmLength, 0, MatrixOrder.Prepend); gr.FillEllipse(Brushes.Red, joint_rect); }
Код начинается с некоторой инициализации, а затем переводит центр координат в середину PictureBox.
Программа должна нарисовать суставы (плечо, локоть и запястье) сверху рук, поэтому метод тянет руку в два этапа. Сначала он рисует руки, а затем натягивает суставы сверху. Он использует один и тот же набор преобразований для каждого.
В коде применяется поворот A1 в плече и рисуется прямоугольник, представляющий первый сегмент руки. Здесь есть одна сложная проблема.
Вращение добавлено к предыдущему переводу, поэтому вращение происходит до перевода, который центрирует плечо. Представьте себе руку в своем собственном мире, координатное пространство с плечом в начале координат. Программа рисует горизонтальный прямоугольник в начале координат для представления первого сегмента руки. Затем преобразования поворачивают его под правильным углом и только затем переводят так, чтобы плечо было центрировано. Это помещает первый сегмент руки в правильное положение.
Затем код должен перейти в положение локтевого сустава. Для этого он добавляет перевод расстояния L1 в направлении X и 0 в направлении Y. Поскольку за этим следует предыдущее вращение, этот перевод происходит в направлении, которое указывает первый сегмент первого плеча. Это ставит начало рисунка в месте локтя. Рисунок переведен, повернут и переведен снова, поэтому он попадает в правильное положение.
Снова представим руку в мировом координатном пространстве и предположим, что вы рисуете локоть в начале координат. Новый перевод перемещает соединение в (L1, 0). Вращение угла A1 вращает сустав в соответствии с вращением первого сегмента плеча. Наконец, перевод плеча перемещает все это, поэтому основание первого сегмента руки центрируется в области рисования.
Код продолжается так много раз, сколько необходимо, чтобы нарисовать все сегменты в руке робота. На каждом шаге он добавляет новые переводы и вращения.
После того, как нарисованы все сегменты руки, код сбрасывает преобразование в исходное, которое центрирует плечо на PictureBox. Затем он снова проходит преобразования, на этот раз рисуя суставы.