Как сделать матрицу html

Обновлено: 07.07.2024

добавим теперь поле для хранения данных и конструктор. Единственный параметр, который нам нужен что определить матрицу (напомню, она у нас квадратная) есть ее размер, то бишь n.

Объявляя переменные приватными (используя слово private), я тем самым ограничиваю доступ к ним извне класса. То есть если кто-то создаст экземпляр класса Matrix, он не сможет напрямую обращаться к полю n и менять его. Вот как я его установил в конструкторе, таким оно и будет. Например:

И хотя технически это ни на что не влияет. Семантически я как бы говорю, что эти данные трогать нельзя, класс лучше знает, как с ними работать.

Давайте еще добавим свойство, которое будет возвращать размер матрицы. Возможно мы помним: свойство — это что-то вроде поля, только которому можно явно указать метод, который вызывается при присваивании и метод, который вызывается при запросе поля.

Давайте попробуем написать программу где используется это класс. Переключимся на функцию Main и напишем код:

если рассмотреть как вызывается код, получится примерно так:

Пока у нас получается пустая матрица

Как мы видим у нас есть объект матрица, внутри которого где-то есть массив для хранения данных. В принципе уже можно заполнить матрицу так

но это не очень красиво. А я хочу, чтобы моя матрица была прям настоящий двумерный массив с дополненными возможностями. То есть чтобы я мог написать вот так:

Такая возможности есть.

И так, отредактируем класс Matrix и определим метод для индексации

Ну вот теперь матрицу можно заполнять:


А давайте добавим еще метод, который будет выводить матрицу в консоль и метод для заполнения матрицы случайными числами:

и можно будет переписать код функции Main так:

Кратко и понятно.

В общем пока вроде ничего интересного. Ну сделали мы обертку двумерного массива. Ну добавили пару методов. А дальше и что? А дальше будем реализовывать операции над матрицами.

И так что есть результат сложения двух матриц? Очевидно, это новая матрица тех же размеров, что и исходная, но где соответствующие элементы сложены. Добавим функцию, которая будет добавлять к исходной матрице другую матрицу и возвращать новую. Правим класс Matrix

попробуем воспользоваться функций чтобы сложить две матрицы. Переключимся на код Main и перепишем его к следующему виду

увидим что-то в этом роде:


А теперь давайте проверим, как работает наша функция сложения:


В принципе код у нас получается весьма хороший. Но возможно вам, как и мне, запись операции сложения через функцию Add

кажется, слишком навороченный. Не правда ли, было бы лучше если б можно было написать код в виде:

Функция для переопределения (или т.н. перегрузки) оператора должна быть задана в следующем виде

собственно, что здесь и зачем попытается рассказать схема:


И вроде если кое-как все понятно, то можно добавить оператор в класс Matrix

вернемся к нашей функции Main и подправим код, так чтобы использовалась операция “+”


кстати переопределять операцию можно сколько угодно раз при условии, что входные параметры будут разные.

Введем оператор добавления числа к матрице. И хотя формальная математика не позволяет нам это сделать. Мы можем рассмотреть эту операцию как добавления единичной матрицы со всеми элементы равными константе к исходной матрице. Т.е. как-то так:

\[\begin1 & 2 & 3\\\ 4 & 5 & 6\\\ 7 & 8 & 9\end + 3 = \begin1 & 2 & 3\\\ 4 & 5 & 6\\\ 7 & 8 & 9\end + \begin3 & 0 & 0\\\ 0 & 3 & 0\\\ 0 & 0 & 3\end = \begin4 & 2 & 3\\\ 4 & 8 & 6\\\ 7 & 8 & 12\end\]

отредактируем наш класс Matrix:

и код функции Main


А что если мы захотим сложить наоборот, число + Матрица, поменяем

а фиг вам, такой код даже не скомпилируется:


И в этом есть доля логики, не все операции коммутативны, то же умножение матрицы. А в программировании все строго.

можно проверить, ошибка должна пропасть, и можно запустить программу:


В принципе с тестами никаких изменений нет, единственное так как мы разработали собственный сложный объект, то нам скорее всего захочется его сравнивать и как правило на предмет равенства, типа совпадают ли две матрицы.

Так же было бы удобно если б матрицу можно было инициализировать с двумерного массива.

Собственно, с этой операции и начнем.

Перегрузка конструктора

Сейчас у нас есть конструктор, которому передаешь целое число n, и он создает матрицу размером \(n\times n\).

Я хочу добавить возможность вызывать конструктор с двумерным массивом в качестве параметра. Для этого мне надо будет создать второй конструктор, но уже с другим типом аргумента.

Когда несколько функций имеют одно название, но разные аргументы, то говорят, что функция перегружена (англ. overload). Собственно, мы перегрузкой и занимались, когда операцию сложения реализовывали. Там мы операцию сложения аж три раза перегрузили.

И так добавим второй конструктор

теперь можно проверить как оно работает:


Пробуем тестировать

Создадим тест. Для этого по старинке тыкаем где-нибудь правой кнопкой внутри класса Matrix и выбираем “Создание модульных тестов”



нам столько тестить лень, поэтому убираем все лишнее и оставляем только один тест:

Так как тестирование как правило сводится к проверке на равенство одних объектов другим, то попробуем создать две одинаковый матрицы и сравнить их:



Короче, чтобы решить эту проблему надо переопределить операцию сравнения то бишь равенства двух матриц.

Переопределение операции равенства

Переопределить равенства немного отличается от переопределения операций. Для этого надо переопределить функцию Equals, она в отличие от операторов сложения/вычитания и т.д. имеет абсолютно конкретный аргумент.


1-07-2018, 20:11


Шаблоны для сайтов


4 505


0

Код для вставки.


HTML5 шаблон магазина

Красивая заглушка для сайта на HTML

Изображения фона изменяются постоянно, можно установить своё время, написать свой текст, есть форма обратной связи, все контакты и важная информация! всё что нужно. Особенно пригодится тем кто хочет приостановить свой сайт на ремонт.

Заглушка сайта HTML5 с двигающимся фоном

щё одна интересная заглушка для вашего сайта! Она написана на HTML5, подойдёт любому, так как многое в ней вы сами сможете изменить. Если ваш сайт находится на ремонте, то этот скрипт как раз для вас

Рисовать фигуры мы умеем, но бывает необходимость эти фигуры перемещать по экрану, поворачивать и менять их размеры. Тут нам поможет Matrix. Будем называть этот объект матрицей. Тем более, что это действительно 3х3 матрица из алгебры.

Матрица умеет выполнять четыре основные операции над фигурой:

translate – перемещение

scale – изменение размера

rotate – поворот

skew - наклон

Рассмотрим эти возможности на примерах. Начнем с перемещения.

Перемещение

Project name: P1441_MatrixTransform
Build Target: Android 2.3.3
Application name: MatrixTransform
Package name: ru.startandroid.develop.p1441matrixtransform
Create Activity: MainActivity

MainActivity.java:


В конструкторе DrawView создаем объекты matrix и path.

В onDraw очищаем path, добавляем к нему пару прямоугольников, чтобы получился крест, и выводим на экран зеленым цветом. Далее очищаем матрицу методом reset и настраиваем смещение на 300 вправо и 200 вниз методом setTranslate. Матрица настроена и готова к выполнению преобразований.

Методом transform объекта path мы выполняем преобразование этого объекта согласно переданной в этот метод матрице. Т.е. фигура path должна сместиться вправо на 300 и вниз на 200.

Включаем синий цвет и выводим измененную фигуру path на экран. На скриншоте видно, что синяя фигура смещена так, как мы и планировали.

Вот и весь алгоритм использования матрицы. Т.е. сначала мы матрицу настраиваем, а потом применяем к какой-либо фигуре и фигура трансформируется согласно настройкам этой матрицы.

Изменение размера

Перепишем класс DrawView:

Рассмотрим тот же path, что и в первом примере. Но теперь для настройки матрицы используем метод setScale. На вход ему передаем коэффициенты изменения размера в ширину (2), в высоту (2.5) и координаты точки (375, 100), относительно которой будет выполнено изменение размера.


Видим, что крест стал в два раза шире и в два с половиной раза выше. Точку, относительно которой было выполнено изменение размера, мы отметили черным кругом.

Существует также вариант метода setScale, который позволяет не указывать точку. В этом случае используется точка (0,0).

Поворот

Перепишем класс DrawView:


Здесь мы в path добавляем два прямоугольника, чтобы получился крест, и рисуем мелкий круг в верхней части креста. Выводим path на экран зеленым цветом.

Далее настраиваем матрицу методом setRotate. На вход метод принимает угол (120) поворота и координаты точки (600,400), относительно которой будет выполнен поворот. Применяем матрицу к фигуре path и рисуем ее синим цветом.

Черным цветом рисуем мелкий круг в точке (600,400), относительно которой был выполнен поворот. Делаем это для наглядности результата. На скриншоте видно, что фигура повернута относительно черного кружка по часовой на 120 градусов.

Существует также вариант метода setRotate, который требует только угол, без координат. В этом случае, в качестве точки поворота будет использована точка (0,0).

Порядок операций

Методы set* настраивают матрицу на выполнение одной определенной трансформации. Но матрица может содержать в себе несколько трансформаций. Если возникает такая необходимость, то необходимо использовать методы pre* и post*.

Методы pre* добавляют трансформацию в самое начало списка трансформаций матрицы. Методы post* - в самый конец.

Причем это может сыграть очень существенную роль в результате выполнения преобразований. Тут та самая ситуация, когда от перемены мест слагаемых сумма очень даже может поменяться.

Рассмотрим пример. Перепишем класс DrawView:

Создаем path из одного прямоугольника и рисуем его черным цветом.

Настраиваем матрицу на поворот на 45 градусов относительно точки (400,200), а затем методом postTranslate добавляем к матрице трансформу перемещения на 500 направо. Применяем результат к path методом transform, который полученный результат поместит в объект pathDst, а path оставит прежним. Это необходимо, т.к. нам дальше еще понадобится оригинальный path. Выводим pathDst зеленым цветом.

Далее делаем все аналогично, только используем метод preTranslate, который добавит трансформу перемещения в начало матрицы. И результат выводим красным цветом.

Для наглядности выведем мелкий круг в точке (400,200), которая у нас являлась точкой поворота в методах setRotate. Эта точка, кстати, является серединой первоначального квадрата.


Как был получен зеленый квадрат? Матрица взяла черный квадрат, повернула (setRotate) его вокруг его же центра на 45 градусов и сместила (postTranslate) вправо на 500. Все примерно так и выглядит на скриншоте.

А вот красный квадрат уехал. Разбираемся. Мы также, как и в случае с зеленым квадратом, сначала попросили матрицу повернуть (setRotate) черный квадрат на 45 относительно своего центра. А вот трансформацию смещения мы добавили методом preTranslate. Т.е. она пошла в начало матрицы и выполнилась до поворота. Т.е. красный квадрат сначала был смещен на 500 вправо, а потом повернут относительно точки (400,200), которая уже вовсе не являлась его центром. И поэтому квадрат уехал вниз по часовой стрелке на 45 градусов относительно точки (400,200).

Этот простой пример позволяет увидеть насколько важно соблюдать порядок трансформаций в матрице. Операции были одни и те же, а разный порядок дал разный результат.

Наклон

Перепишем класс DrawView:


path содержит один прямоугольник. Выводим его на экран черным цветом.

Далее настраиваем матрицу на смещение на 200 вправо. И методом postSkew настраиваем наклон. На вход ему передаем значения наклона по оси X (0), наклона по оси Y (0.5) и координаты точки, относительно которой будет выполнен наклон (300,100). Применяем матрицу к path и рисуем результат. Также для наглядности рисуем круг в точке, относительно которой был наклон.

На скриншоте это левый зеленый наклоненный квадрат. Он наклонен по оси Y с коэффициентом 0.5. Видим, что его правая (относительно точки наклона) часть ушла вниз.

Аналогично рисуем второй зеленый квадрат, но точку наклона используем другую. Тут уже видно, что при том же наклоне (0.5 по оси Y) левая часть уходит вверх.

Далее аналогично выводим два синих квадрата, но у них уже наклон идет по оси X. Видно, что нижняя часть при этом наклоняется вправо, а верхняя влево.

Несколько дополнений к наклону.

Если задавать отрицательные значения наклона по осям, то направления наклона поменяются.

Разумеется, можно сразу задавать наклон по обоим осям. Просто в этом примере для упрощения мы наклоняли каждый квадрат только по какой-то одной оси.

Точка наклона может быть любой, она не должна принадлежать фигуре. Есть аналог метода setSkew, который принимает только коэффициенты наклона, а в качестве точки использует (0,0).

Советую вам поэкспериментировать и позадавать различные значения наклонов по осям, если еще не до конца понятен механизм наклона.

Map методы

mapRadius – даете на вход радиус (если собираетесь трансформировать круг), а метод вам вернет значение радиуса после трансформаци

mapPoints – даете массив точек, матрица выполняет над ними свои операции преобразования и возвращает вам в результате новый массив точек

mapVectors – то же, что и mapPoints, но преобразования перемещения выполнены не будут

mapRect – возьмет на вход прямоугольник, выполнит для него преобразование и вернет прямоугольник, составляющий границы получившейся фигуры. Рассмотрим этот метод на примере.

Перепишем класс DrawView:

К path добавляем квадрат и выводим черным цветом.

Настраиваем преобразования матрицы. Это поворот на 45 градусов относительно центра квадрата (150,150). Затем растянем его по горизонтали на 1.2 и сожмем по вертикали на 0.8. И переместим на 200 вправо.

Применяем матрицу к path и выводим результат зеленым цветом.

Далее выполним метод mapRect, который возьмет прямоугольник rectf, выполнит над ним все преобразования матрицы, и в rectfDst запишет границы получившейся фигуры. Выведем эти границы синим цветом.


Видим, что зеленым нарисована фигура, которая получилась из прямоугольника после преобразований, а синим – границы фигуры, которые были получены из прямоугольника методом mapRect. Т.е. mapRect сообщает нам, какие границы будут у прямоугольника после преобразований.

Операции над матрицами

set – считает настройки с переданной матрицы в нашу матрицу

setConcat – соберет преобразования из двух матриц в вашу матрицу

preConcat – добавит преобразования из переданной матрицы в начало вашей матрицы

postConcat – добавит преобразования из переданной матрицы в конец вашей матрицы

invert – настроит вашу матрицу на преобразования, обратные тем, на которые настроена переданная матрица

Мы рассмотрели почти все методы матрицы. Есть еще два интересных и полезных метода: setRectToRect и setPolyToPoly. Но по ним получилась целая простыня объяснений и я вынес их в следующий урок.

На следующем уроке:

- разбираемся с методами setRectToRect и setPolyToPoly

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

- новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме


Анимация экрана из фильма матрица

Комментарии

Похожие статьи

Популярные статьи

Новогодняя мотня от Яндекса 2.1

SnowFall — Анимация падающего снега

Падающий снег на CSS

Реклама

Опрос

В редакторе кода я предпочитаю тему оформления

Подпишись

Присоединяйся, чтобы узнать все самое интересное для frontend разработчика и анонсы статей с сайта.

Разное

Реклама

Свежие статьи

© 2011 — 2020 Скрипты для сайтов

Установите актуальную версию вашего браузера или одну из современных альтернатив.

Мы используем файлы cookie.
Продолжая навигацию по веб-сайту, вы соглашаетесь на использование cookie-файлов.

Читайте также: