Pull to refresh

Comments 65

Очень подробно и понятно. Что касается изометрики, не совсем мне кажется доступно описано.
Но так и потянуло открывать редактор и пробывать различные трансформации.
Спасибо, очень познавательно. А про кривые безье будет статья?
Кривые Безье — это намного проще, на статью не тянет. Глянем на MDC интерфейс:
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

Тут главное разобраться за какую точку отвечает каждый из аргументов. Вы можете использовать LibCanvas PathBuilder для экспериментов.



Оранжевая точка — это точка, из которой мы начинаем рисовать кривую, её положение показывает где закончился путь перед этим, например от аргумента moveTo или последняя точка предыдущего вызова bezierCurveTo.

Аргументы x, y отвечают за изменения положения жёлтой точки, которая указывает куда следует проложить кривую, аргументы cp1x, cp1y за изменения положения контрольной розовой точки, а cp2x, cp2y – контрольной голубой.
Извините за не энциклопедическое объяснение)
Спасибо, понятно. Просто я уж коль вы разбираете в геометрических преобразованиях, хотел бы поинтересоваться как построить параллельную кривую, кривой бизье. Заданную 3мя точками. Надеюсь понятно что я имею в виду (например железнодорожные шпалы).
Для того, чтобы построить параллельную кривую необходимо сдвинуть на определённое значение х или у. Главное — сохранить растояние между всеми точками фигуры. К примеру, если Вам нужно построить параллельную кривую справа от первичной, то необходимо все иксы увеличить на N.
Можно, но таким образом мы получим не равноценные окончания отрезков. Ладно, без примера сложно объяснить. Там нужно вычислять новые точки. У меня есть идея, думал может еще, что подскажите. Спасибо. Будет интересно нарисую.
Мне интересно. Особенно про пункт «неполноценные окончания». Что вы имеете ввиду? Если так критично сделать клона кривой — почему бы ее на нарисовать в буфер, а потом из него — две кривых
Буфер не нужен. Мне скорее требуется не клона, а кривую, которая будет полностью параллельна. Завтра я напишу комментарий тут, где приведу пример, и решение свое. Сегодня просто не успею.
Насколько я понял из описания, Вам нужна эквидистанта.
И так, у нас есть кривая, построенная по трем точкам.

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

На параллельные путь, ЖД не очень похоже.
Во что мне бы хотелось видеть.

Красная и синяя кривые.

Теперь опишу алгоритм как я это получаю.
Проводим отрезки АК и ВК в 3 точку кривой бизье.
Перпендик. им я строю прямые a и b. На этих прямых откладываю 2 равных отрезка AC и BD.
Это и будут новые точки кривой бизье. Но как найти 3ю точку.

Я провожу 2 параллельные прямые DF || BK и CF || AK.
И на их пересечении я нахожу точку F. Какая и является искомой. Вот так, я строю.
Сам алгорим я ещё не проверил(до этого я искал по другому, но оказалось ошибачно), может это и не правильно, или может есть ещё какой то более простой способ, поэтому и спрашиваю.

И ещё. Так как я не знаю как построить параллельные(может есть алгорим). То провожу перпендикулярные прямые, не только к точкам B и A. Но и в точку К я опускаю 2 перпендикуляра как к одной прямой так и к другой.

Во-первых, у Вас на картинках изображена квадратичная кривая Безье, это на всякий случай.

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

Но теперь, зная название, Вам будет гораздо проще найти информацию по предметной области. У меня, например, нашлась вот такая забавная статья.
картинки не открываются
Да, знаю. Сам сервис не работает. В понедельник, залью на другой.
Приятно когда девушки пишут такие статьи. Спасибо, только начал вникать в Canvas, будет полезно.
К тому же девушки, которым 19 лет o_O
UFO just landed and posted this here
Вы знаете много 19-ти летних девушек, пишуших на хабр про элементарную геометрию в джаваскрипте? :-)
UFO just landed and posted this here
неправильно дано определение параметрам m11,m12,m21,m22.
m11 = scaleX * cos(alpha),
m12 = scaleY * sin(alpha),
m21 = -scaleX * sin(alpha),
m12 = scaleY * cos(alpha),
где scaleX,scaleY — сжатие растяжение вдоль соответствующей оси, а alpha — угол поворота.
И на сколько это поможет не понимающим людям понять, что делает каждый из аргументов? Цель этой статьи ведь не в том, чтобы процитировать технические определения, а обьяснить доступным языком, что можно было без заминки использовать трансформации
эта матрица является обобщением методов scale, translate и rotate(произведением матриц) и мне кажется если люди поняли как работают эти методы по отдельности, то их не нужно вводить в заблуждение, а дать точное описание параметров
Точное описание параметров можно найти в любой «умной» статье про трансформации. Они дают мало понимания менее опытным программистам. Важно понять, как оно работает, а не заучить технические определения
Хочу обратить внимание — я не спорю, что желательно глубокое понимание принципов трансформации, более того, сам достаточно хорошо разбираюсь в этом, но такие детали в ЭТОЙ статье только запутают разбирающегося. Любой желающий, прочтя нашу ветку комментариев в легкостью найдет более точные, но менее очевидные описания.
Я так же не спорю. Просто я не понимаю, то описание которое дал автор, мне кажется оно не корректным. Хотя для новичков — это старт, чтобы понять предмет трансформации.
спросите у новичков, насколько точное определение помогает им понять предмет трансформации
Вы зануда.

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

ЗЫ. Это напоминает мне холивар: нужно ли программисту знание математики.
UFO just landed and posted this here
нуу. для поворота есть метод rotate
когда работаешь с canvas напрямую, помогаю только формулы, а не подбор коэффициентом
UFO just landed and posted this here
немножко иксы-игреки перепутаны.
UFO just landed and posted this here
то что я написал это полный вариант, матрица трансформации — это перемножение трех матриц: поворота, растяжения и параллельного переноса.
UFO just landed and posted this here
я подправил только коэффициенты m11-m22. Я вам говорю про матрицу трансформации на плоскости. Она имеет размер 3х3, и да на плоскости существую только поворот, сжатие и параллельный перенос.
UFO just landed and posted this here
забыл про наклон упомянуть, его обычно не относят к базовой трансформации, хотя в матрицы трансформации он присутствует, в коэффициентах m11-m22

Каюсь привел не до конца верные формулы.
и я повторюсь для меня проще сухие формулы, я ни кого не заставляю ими пользоваться.
UFO just landed and posted this here
только поворота и растяжения. для переноса нужно вводить третюю координату.
перенос это самая простая трансформация. Она имеется даже в R1.
"… он шире в два раза чем выше"

После прочтения вспомнилось:
Любая девушка может доказать, что крокодил более зеленый чем широкий...)))
Эх, жаль в канвасе нет матричных преобразований цвета пикселей… Руками это делать как-то чертовски долго выходит.
В тестировании матрицы ввел ошибочные параметры — канва упала, и перестала реагировать даже на корректные данные. Помог F5.
А что вы ввели? Но вообще, я вечером оберну в try-catch.
4й параметр = 0
в изометрии между тайлами белые точки. как это побороть?
Накладывать с нахлестом в треть пикселя:
ctx.drawImage(img,
	128*sprite, 0, 128, 128,
	64*x, 64*y, 64, 64
);
// =>
ctx.drawImage(img,
	128*sprite, 0, 128, 128,
	64*x, 64*y, 64.3, 64.3
);
ну так сделайте это в примере
Где же Ваши собственные фотографии на этот раз?
Как к чему? Применять матрицу преобразований, очень удобно было бы.
Я сейчас для развлечения и изучения canvas пишу игру Scorch, мне там понадобилась совмещать трансформации, крутить вокруг выбранной точки, для этого просто написал Matrix2d

Очень удобно пользоваться:

new Matrix2d().
	Rotate(angle, rotationPoint).
	FlipY(rotationPoint).
	CreateTransform(context);


function Matrix2d () {
	var _matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
	
	var CalcOffset = function (matrix) {
		var x = matrix[0][2] * matrix[0][0] + matrix[1][2] * matrix[0][1];
		var y = matrix[0][2] * matrix[1][0] + matrix[1][2] * matrix[1][1];
		
		matrix[0][2] -= x;
		matrix[1][2] -= y;
		
		return matrix;
	}
	
	var Multiply = function (matrix) {
		var mulMatrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
		
		for (var x = 0; x < 3; x++) {
			for (var y = 0; y < 3; y++) {
				var sum = 0;
				
				for (var dim = 0; dim < 3; dim++) {
					sum += _matrix[y][dim] * matrix[dim][x];
				}
				
				mulMatrix[y][x] = sum;
			}
		}
		
		_matrix = mulMatrix;
	}
	
	this.Rotate = function (angle, point) {
		var sin = Math.sin(angle);
		var cos = Math.cos(angle);
		
		Multiply(CalcOffset([
			[cos, -sin, point.x],
			[sin, cos, point.y],
			[0, 0, 1]
		]));
		
		return this;
	}
	
	this.FlipY = function (point) {
		Multiply(CalcOffset([
			[-1, 0, point.x],
			[0, 1, point.y],
			[0, 0, 1]
		]));
		
		return this;
	}
	
	this.FlipX = function (point) {
		Multiply(CalcOffset([
			[1, 0, point.x],
			[0, -1, point.y],
			[0, 0, 1]
		]));
		
		return this;
	}
	
	this.FlipXY = function (point) {
		Multiply(CalcOffset([
			[-1, 0, point.x],
			[0, -1, point.y],
			[0, 0, 1]
		]));
		
		return this;
	}
	
	this.CreateTransform = function (context) {
		context.transform(
			_matrix[0][0],
			_matrix[1][0],
			_matrix[0][1],
			_matrix[1][1],
			_matrix[0][2],
			_matrix[1][2]);
		
		return this;
	}
}
Видел, но только для перемножений матриц брать её не имеет смысла. У них для 2d используется матрица 2x2 — у меня 3x3, что позволяет заодно и смещения считать, крутить вокруг нужной точки, отражать вокруг нужной точки. Плюс возможность цепочки трансформаций. Добавление новой функциональности сводится к добавлению 9 строк кода и новой матрицы в них.
В моём случае поддержка и расширение легче и, самое главное, кода намного меньше.
Да и условия лицензии не надо исполнять ;-)
Sign up to leave a comment.

Articles