Получить все точки отрезка прямой?
Как получить все точки отрезка прямой (на canvas)?
Известно x1, y1, x2, y2 Допенькал как получить точки прямой по Алгоритму Брезенхема до 45* градусов. Если переставить x и y можно даже получить все точки до 90*. Но не могу понять как получить все точки, если x2 < x1 или y2 < y1 Может как-то через отражение? |
Если я правильно понял задачу, то
http://www.cleverstudents.ru/line_an..._segments.html |
Gozar,
:write: нарисовать чёрным по белому на невидимом холсте потом прогнать весь холст записав в массив все точки цвета |
Цитата:
kobezzza, Хотелось бы в программном коде, а не геометрии. В алгоритмах куча оптимизаций, а я буду изобретать велосипед. А по Брезенхему не встречался? По сути мне нужно достроить между точками прямую, точек у меня таких много и они динамически создаются очень быстро. |
Ну я хз про оптимизации, но есть общая формула:
x / a + y / b = 1 где a и b удаление от начала координат по X и Y, т.е. подставляешь a и b, затем делаешь шаг по X или Y (шаг определяешь сам, например 1px) и вычисляешь второе значение. Думаю, что есть специальные алгоритмы, но я тут не в теме особо. |
kobezzza,
Спасибо за участие, я формулы видел, а потом посмотрел лекцию по графике и понял, что лучше взять готовый алгоритм, с оптимизацией. Нашел тут на каком-то неизвестном языке програ-я написан, ща попробую переписать :D |
:write: мысли вслух любой блок анимации на js выдаст необходимый массив точек --даже точность можно регулировать.
|
Цитата:
|
Gozar,
<script> var x = 5, y = 5, x2 = 2, y2 = -10; var time = Math.abs(x - x2); for (var i=0; i<=time; i++) { var delta = i/time ; var a = delta*(x2 - x) + x; var b = delta*(y2 - y) + y; document.write([a,b]+"<br>") } </script> |
:write:
<script> var x = 50, y = 50, x2 = 20, y2 = -10; var time = Math.max( Math.abs(x - x2), Math.abs(y - y2));//для повышения точности выбираем что сильнее изменилось, для ускорения выбор наоборот min for (var i=0; i<=time; i++) { var delta = i/time ; var a = delta*(x2 - x) + x; var b = delta*(y2 - y) + y; document.write([Math.round(a),Math.round(b)]+"<br>") } </script> |
рони,
Вот тебе функция: //<canvas id="canvas" width="300" height="300" style="border: 1px solid #000"></canvas> function setPixel (x, y) { ctx.beginPath(); ctx.moveTo(x,y); ctx.arc(x, y, 1, 0, Math.PI*2, true); ctx.fill(); ctx.closePath(); } var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,1)'; Можешь нарисовать на канвас то, что у тебя получилось? Я не очень понимаю куда мне подставлять отрицательные значения из твоего кода. Вот координаты двух линий: x1 = 10, y1 = 10, x2 = 100, y2 = 100; x1 = 10, y1 = 100, x2 = 100 y2 = 10; |
Цитата:
function drawLineTo(x1, y1, x2, y2) { var deltaX = Math.abs(x2 - x1), deltaY = Math.abs(y2 - y1), signX = x1 < x2 ? 1 : -1, signY = y1 < y2 ? 1 : -1, error = deltaX - deltaY; setPixel(x2, y2); while (x1 != x2 || y1 != y2) { setPixel(x1, y1); var error2 = error * 2; if (error2 > -deltaY) { error -= deltaY; x1 += signX; } if (error2 < deltaX) { error += deltaX; y1 += signY; } } } |
Цитата:
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> </head> <body> <canvas id="canvas" width="300" height="300" style="border: 1px solid #000"></canvas> <script> function setPixel (x, y) { ctx.beginPath(); ctx.moveTo(x,y); ctx.arc(x, y, 1, 0, Math.PI*2, true); ctx.fill(); ctx.closePath(); } var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,1)'; x1 = 10, y1 = 10, x2 = 100, y2 = 100; var time = Math.abs(x1 - x2); for (var i=0; i<time; i++) { var delta = i/time ; var a = delta*(x2 - x1) + x1; var b = delta*(y2 - y1) + y1; setPixel(a,b) } x1 = 10, y1 = 100, x2 = 100, y2 = 10; var time = Math.abs(x1 - x2); for (var i=0; i<time; i++) { var delta = i/time ; var a = delta*(x2 - x1) + x1; var b = delta*(y2 - y1) + y1; setPixel(a,b) } </script> </body> </html> |
JsLoveR,
Спасибо. Я нашел немного другой, он по скорости чуть чуть быстрее: function setLine (x1, y1, x2, y2) { var x = x1, y = y1; var dx = Math.abs(x2-x1), dy = Math.abs(y2-y1); var sx = (x2-x1)>0?1:((x2-x1)==0?0:-1); var sy = (y2-y1)>0?1:((y2-y1)==0?0:-1); var tx, ty; var z, scount, count, dcount; if (dx>=dy) { tx = sx; ty = 0; } else { z=dx; dx=dy; dy=z; tx=0; ty=sy; } scount = 2*dy; count = scount-dx; dcount = count-dx; for(;;) { dx -= 1; if (dx < -1){ break; } setPixel(x, y); if (count >= 0) { x+=sx; y+=sy; count += dcount; } else { x+=tx; y+=ty; count += scount; } } } |
Цитата:
эт на будущее, по скольку спускаемся на уровень абстракции ниже ближе к железу, то это раз в сто быстрее чем яваскриптом считать Этим же трюком можно чекать пересекаются ли фигуры в физических яваскрипт движках) аппаратное ускорение хули |
for(;;) не пиши так больше, пиши while(true) как все нормальные люди, и даже не while(1), именно while(true), как взрослый образованный человек, не дикарь. |
рони,
Что-то не работает: <!DOCTYPE HTML> <html> <head> <title>Untitled</title> </head> <body> <canvas id="canvas" width="1000" height="1000" style="border: 1px solid #000"></canvas> <script> function setPixel (x, y) { ctx.beginPath(); ctx.moveTo(x,y); ctx.arc(x, y, 1, 0, Math.PI*2, true); ctx.fill(); ctx.closePath(); } var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,1)'; function ronyLine (x1, y1, x2, y2) { var time = Math.abs(x1 - x2), a, b, delta, i; for (i=0; i<time; i++) { delta = i/time; a = delta*(x2 - x1) + x1; b = delta*(y2 - y1) + y1; setPixel(a,b) } } for(var i=0;i<1000;i+=1) { ronyLine(10, 10, i, 200); } </script> </body> </html> Упс, работает, но что-то мне подсказывает, что лучше так не делать :) |
__он_самый__,
Цитата:
|
Gozar,
28 строка зачем? |
Цитата:
|
Цитата:
|
Gozar,
ты уже сам убрал косяк -- аргументы перезаписывались в строке 28 |
рони,
Ты видел результат? Почему он такой? Вначале не линия, а сетка. |
Gozar,
точность расчётов <!DOCTYPE HTML> <html> <head> <title>Untitled</title> </head> <body> <canvas id="canvas" width="1000" height="1000" style="border: 1px solid #000"></canvas> <script> function setPixel (x, y) { ctx.beginPath(); ctx.moveTo(x,y); ctx.arc(x, y, 1, 0, Math.PI*2, true); ctx.fill(); ctx.closePath(); } var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,1)'; function ronyLine (x1, y1, x2, y2) { var time = Math.max( Math.abs(x1 - x2), Math.abs(y1 - y2)), //оптимальная точность a, b, delta, i; time = 1000// точность для маньяков for (i=0; i<time; i++) { delta = i/time; a = delta*(x2 - x1) + x1; b = delta*(y2 - y1) + y1; setPixel(a,b) //setPixel(Math.round(a),Math.round(b)) //по желанию } } for(var i=0;i<1000;i+=10) { ronyLine(10, 10, i, 200); } </script> </body> </html> |
рони,
Это все прикольно, но в тесте пикселы закрашены не все, а значит ф-ия не подходит, с учетом того, что она еще и немного медленнее других. |
Gozar,
померяй этот вариант ))) <!DOCTYPE HTML> <html> <head> <title>Untitled</title> </head> <body> <canvas id="canvas" width="1000" height="520" style="border: 1px solid #000"></canvas> <script> function setPixel(x, y) { ctx.beginPath(); ctx.moveTo(x, y); ctx.arc(x, y, 1, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); } var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,1)'; function ronyLine(x1, y1, x2, y2) { var x = Math.abs(x1 - x2),y = Math.abs(y1 - y2) ; var time = Math.sqrt(x*x + y*y)|0, // больше точек, чем это число на линии нет a, b, delta, i; var xx = (x2 - x1) + x1, yy = (y2 - y1) + y1 ; //типа кеш for (i = 0; i < time; i++) { delta = i / time; a = delta * xx; b = delta * yy; setPixel(a, b) } } for (var i = 0; i < 1000; i += 10) { ronyLine(10, 10, i, 500); } </script> </body> </html> |
Иногда можно заюзать линейную "кривую" безье.
function bezierLineTo(x1, y1, x2, y2) { var step = 0.0001; //для большей точности можно находить дистанцию между точками, тогда step = 1 / distance for (var t = 0; t < 1; t += step) { var x = (1 - t) * x1 + t * x2; var y = (1 - t) * y1 + t * y2; setPixel(x, y); } } |
Цитата:
Кстати кто-нибудь знает какой-нибудь очень быстрый рандом? вот этот: Math.floor(Math.random() * (max - min + 1)) + min; очень медленный. Подойдет от 1 до 360. |
Gozar,
а если один раз сформировать массив рандомный и пользоваться |
Цитата:
1. По точкам строишь вектор. Координаты вектора: x = x2-x1, y = y2-y1 2. Находишь длину (модуль) вектора: sqrt(x^2 + y^2) Если требуется, переводишь декартовы координаты в полярные (или наоборот). |
Цитата:
Цитата:
генератор цепочек случайных данных <!DOCTYPE HTML> <html> <head> <title>Untitled</title> </head> <body> <script> var time = new Date(); function rund(e, f) { function d(b) { for (var a = b.length - 1; 0 < a; a--) { var c = Math.floor(Math.random() * (a + 1)), d = b[c]; b[c] = b[a]; b[a] = d } return b } var a = [], c = []; for (i = 0; i < e; i++) a[i] = i + f; d(a); return function () { var b = a.shift(); c.push(b); 1 == a.length && (d(c), a = a.concat(c), c = []); return b } }; var len = 360, min = 1, z = rund(len,min), i; var arr = []; for (i = 0; i < 15000; i++) { //можно любой длины равномерность случайности сохранится или просто вместо random использовать z() arr[i]= z() } alert((new Date).getTime() - time.getTime()); //10ms на генерацию 15000 вариантов for (var i=0; i<arr.length; i++) {document.write(arr[i]+" ")} //для примера </script> </body> </html> |
nerv_,
Как найти все x между x1 и x2? и с y тоже самое. |
Цитата:
Можно задать неравенством / множеством. Но тебе данные случаи, как я понял, не нужны. Скорее всего ты поставил задачу неправильно, вследствии чего можешь найти решение. Попробуй сформулировать задачу в более общем виде. |
:write: на всякий случай случайный ... но медленнее(чуть) и конечно менее случайный (зато свой random, не использует встроенный метод Math.random)
http://chancejs.com/ <!DOCTYPE HTML> <html> <head> <title>Untitled</title> </head> <body> <script type="text/javascript" src="http://chancejs.com/chance.js"></script> <script> var time = new Date(); var arr = []; for (var i=0; i<15000; i++) {arr[i]=chance.integer({min: 1, max: 360})} alert((new Date).getTime() - time.getTime()); //10ms на генерацию 15000 вариантов for (var i=0; i<arr.length; i++) {document.write(arr[i]+" ")} </script> </body> </html> |
Цитата:
Если хочешь могу написать, что нужно найти не все точки прямой, а координаты всех точек отрезка прямой на плоскости. Хотя я думал что если canvas то должно быть понятно, что на плоскости. Хотя я уже подумываю о нахождении точек кривой безье :) |
Цитата:
Цитата:
|
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Любая метрическая система делит что-то на секции с определнной погрешностью.
В нашем случае секции - это пиксели. Например прямая длиной 137px имеет 137 точек. Gozar x2 - x1 = x длина первого катета y2 - y1 = y длина второго катета Квадрат гипотинузы равен сумме квадратов катетов... Если хочется получить кординаты какой то точки на гипотинузе то составляй тройную пропорцию. Надеюсь я правильно понял вопрос |
Часовой пояс GMT +3, время: 00:30. |