Получить все точки отрезка прямой?
Как получить все точки отрезка прямой (на 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, время: 15:06. |