forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Основной форум (http://forum.boolean.name/forumdisplay.php?f=49)
-   -   Отрисовка толстых линий (http://forum.boolean.name/showthread.php?t=11746)

VotapilD 16.01.2010 22:29

Отрисовка толстых линий
 
Как сделать толстую линию? Даже идей нет, как и наработок. И так же дела с векторами состоят(

Reizel 16.01.2010 22:36

Ответ: Ошибка синтаксиса.
 
А какя связь между названием темы и ее содержанием?

Reizel 16.01.2010 22:37

Ответ: Ошибка синтаксиса.
 
А вообще у линии есть угол , вот собственно толстая линия - это несколько обычных линий под одним и тем же углом. Значит, к координате X надо прибавлять косинус угла, а к Y - синус. Учите тригонометрию :)

VotapilD 16.01.2010 22:46

Ответ: Ошибка синтаксиса.
 
А как угол найти? ))

Reizel 16.01.2010 22:50

Ответ: Ошибка синтаксиса.
 
Ну ты же паскаль юзаешь, ты и должет знать. В Блице есть команда Atan2, собственно она то и возвращала угол...

VotapilD 16.01.2010 23:26

Ответ: Ошибка синтаксиса.
 
И какая же в Паскале? Мой гугль не помогает) И хелп по МП тож

ViNT 16.01.2010 23:35

Ответ: Ошибка синтаксиса.
 
В MP не все так просто, надо свой алгоритм выдумывать.
Сейчас с наскока сообразить не могу, может потом поковыряюсь

Reizel 17.01.2010 10:16

Ответ: Ошибка синтаксиса.
 
Ну можно логически подумать.... Есть две точки на плоскости, соответственно они представляют из себя прямоугольный треугольник. Ну вот значит надо вычислить этот угол, зная его синус(или косинус) . А найти этот самый синус можно, разделив длину противолежащего катета к гипотенузе. Косинус - эт вроде прилежащего к гипотенузе. тангенс - прилежащего к противолежащему...Ну в общем зная синус и косинус угла наверно сожно найти и угол :)

cherepets 17.01.2010 11:51

Ответ: Ошибка синтаксиса.
 
я када граф часы делал, рисовал часовую стрелку как-то так:

drawline(x,y,w,h);
drawline(x+1,y,w,h);
drawline(x,y+1,w,h);

примерно ровно, если хочешь узнать точнее копай исходник в конце темы с noxOS

Tronix 17.01.2010 13:16

Ответ: Ошибка синтаксиса.
 
Ваще ничо не понял. Толстая линия == несколько тонких линий. В чем проблема?

ViNT 17.01.2010 13:45

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от Tronix (Сообщение 133782)
Ваще ничо не понял. Толстая линия == несколько тонких линий. В чем проблема?

По вертикали и горизонтали никаких, а так - угол (относительно OX) может быть a<90, 90<a<180, 180<a<270, 270<a<360, во всех этих случаях линии нужно рисовать по-разному.

impersonalis 17.01.2010 16:08

Ответ: Ошибка синтаксиса.
 
рисуйте окружности. Радиус R - толщина линии. Над расстояниям - надо подумать..

Tronix 17.01.2010 23:35

Ответ: Ошибка синтаксиса.
 
Вложений: 1
Ну не знаю. Если MP не позволяет под углом линии рисовать - то классически по Брезенхаму. Всю жизнь так рисовал. Даже интро запиливал неплохие.

VotapilD 18.01.2010 16:51

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от impersonalis (Сообщение 133797)
рисуйте окружности. Радиус R - толщина линии. Над расстояниям - надо подумать..

я об этом думал и даже что-то вывел(через формулу y=kx+b и последующем подставлением(долго)), но что делать с вектором?(Lib_vector)

Цитата:

Сообщение от cherepets (Сообщение 133779)
drawline(x,y,w,h);
drawline(x+1,y,w,h);
drawline(x,y+1,w,h);

не понял. Это разве не треугольник получается?

Павел, угол можно найти зная синус ИЛИ косинус, вроде=) А их найти по отношению проекций... Но получится ли.. Или зачем нам теперь вообще угол?
Цитата:

Сообщение от Павел
Значит, к координате X надо прибавлять косинус угла, а к Y - синус.

Вот и решение? О_О(/me сомневаиццо и затупилось)

Цитата:

Сообщение от Tronix (Сообщение 133871)
Ну не знаю. Если MP не позволяет под углом линии рисовать - то классически по Брезенхаму. Всю жизнь так рисовал. Даже интро запиливал неплохие.

Я немного не въехал, ни в метод, не в язык на котором написанно...

{130 просотров за 2 дня О_О}//offtop

VotapilD 22.01.2010 20:31

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от Tronix (Сообщение 133871)
Ну не знаю. Если MP не позволяет под углом линии рисовать - то классически по Брезенхаму. Всю жизнь так рисовал. Даже интро запиливал неплохие.

O_O А не долговато ли? Толстую линию по Брезенхаму?

Tronix 22.01.2010 20:58

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от VotapilD (Сообщение 134427)
O_O А не долговато ли? Толстую линию по Брезенхаму?

Да нет вроде. Ну можно по DDA, оно вообще летает
UPD: А не, DDA тот еще тормоз, ибо деление....

Tronix 23.01.2010 01:08

Ответ: Ошибка синтаксиса.
 
Вложений: 1
Вообще не нужны никакие брезенхамы имхо. Толстая линия - это всего лишь много тонких линий и не более )) Вот прям щаз на коленке накатал. Если не задавать гигантскую ширину, вполне может прокатить ))) Писалось за 5 мин, поэтому если сильно накосячил прошу не пинать больно.
PHP код:

program NewProject2;
//
// Simle draw lines with width demo program. (c) Tronix, 2010.
//
Var
gw,gh integer;        // screen width and height
xx1,xx2,
yy1,yy2 integer// random coordinates for line
width integer;        // line width

// Very simple procedure for drawing lines with any width
// x1,y2,x2,y2 - screen coordinates
// d - line width
Procedure BigLine(x1,y1,x2,y2,dinteger);
Var 
iswap integer;
Begin
    
If x1 x2 then             // vertical line
        
Begin
            
For := d div 2 d to d div 2 do DrawLine(x1+i,y1,x2+i,y2);
        
End
    
else
    If 
y1 y2 then            // horizontal line
        
Begin
            
For := d div 2 d to d div 2 do DrawLine(x1,y1+i,x2,y2+i);
        
End
    
else
        
Begin
            DrawLine
(x1,y1,x2,y2);        // draw sinle line
            
If 1 then                      // if width > 1 then draw left and right lines
                
Begin
                    
If x1 x2 then                // sorting coordinates if needed
                        
Begin
                            swap 
:= x2;
                            
x2 := x1;
                            
x1 := swap;
                            
swap := y2;
                            
y2 := y1;
                            
y1 := swap;
                        
End;
                    If (
x1 x2) and (y1 y2then     // detect line direction
                        
Begin                                                         // left-to-right line
                            
For := 1 to d div 2 do                
                                
Begin
                                    DrawLine
(x1,y1+i,x2-i,y2); //left side
                                    
DrawLine(x1+i,y1,x2,y2-i); //right side
                                
End
                        End
                        
else                                                         // righ-to-left line
                            
Begin
                            
For := 1 to d div 2 do
                                
Begin
                                    DrawLine
(x1+i,y1,x2,y2+i); // left side
                                    
DrawLine(x1,y1-i,x2-i,y2); // right side
                                
End
                        End
;
            
End;
    
End//if
End;

begin
    Randomize
;
    
gw := GetWidth;
    
gh := GetHeight;
    
SetColor(0,0,0);
    
FillRect(0,0,gw,gh);    // clear screen. black
    
    
repeat
        xx1 
:= Random(gw);
        
yy1 := Random(gh);        // random line coordinates
        
xx2 := Random(gw);
        
yy2 := Random(gh);
        
width := Random(10)+1// line width >= 1

        
SetColor(Random(255),Random(255),Random(255)); // random color for line
        
bigLine(xx1,yy1,xx2,yy2,width);                              // DRAW it Now :)))

        
SetColor(255,255,255);                                 // white color for debug msg
        
DrawText('X1= '+xx1+' Y1= '+yy1,0,0);
        
DrawText('X2= '+xx2+' Y2= '+yy2,0,10);
        
DrawText('W= '+width,0,20);                        // draw debug information

        
repaint;    
        
repeat delay (10until getkeyclicked <> KE_NONE;  // waiting for any key
        
SetColor(0,0,0); // clear screen
        
FillRect(0,0,gw,gh);
        
repaint;
    
until GetKeyPressed KE_STAR// exit if 'star' key will be pressed
end


ViNT 23.01.2010 01:54

Ответ: Ошибка синтаксиса.
 
Нашел в нете упоминание о классе Graphics2D для java, там есть разные стили линий, и другие графические инструменты, попробую под него либу накатать (если NetBeans на семерку встанет).

Tronix 23.01.2010 12:27

Ответ: Ошибка синтаксиса.
 
Вложений: 1
А вообще погорячился я. Интересная задачка на самом деле... После некоторых раздумий пришел к банальному - рисуем основную линию по Брезенхему, причем из каждой нарисовоной точки рисуем еще одну линиию перпендикулярно нашей основной линии.

Ну либо тупо рисовать закрашенный полигон, но это уже деление-умножение, причем подозреваю вешественное. Хотя не известно что еще быстрее будет...

UPD: ыыыыы, оказывается изобрел велосипед - http://homepages.enterprise.net/murp...ine/index.html :)

VotapilD 23.01.2010 14:19

Ответ: Ошибка синтаксиса.
 
А что если и правда sin&cos? Седне в школе по памяти на алгебре(на контрольной=) ) накатал:

a:=abs(x1-x2);//катит у
b:=abs(y1-y2);//катит х
c:=sqrt(a*a+b*b);//гипотенуза
cos:=b/c;//cosB
sin:=a/c;//sinB угол против стороны У
for i:=-2 to 2 do begin
x1:=x1+cos*i;//
y1:=y1+sin*i;// Переносим точки, так
x2:=x2+cos*i;// чтобы линия была параллельна...
y2:=y2+sin*i;//
DrawLine(trunc(x1),trunc(y1),trunc(x2),trunc(y2));
end;
repaint;

Павел, я правильно вас понял?
Цитата:

Сообщение от Павел (Сообщение 133743)
А вообще у линии есть угол , вот собственно толстая линия - это несколько обычных линий под одним и тем же углом. Значит, к координате X надо прибавлять косинус угла, а к Y - синус. Учите тригонометрию :)

Проверте плиз. Я щас без телефона, а эмуль под линь я пока не нашёл... И если это правильно то останется лишь придумать способ увеличение длины отрезка по краям)

VotapilD 23.01.2010 14:54

Ответ: Ошибка синтаксиса.
 
Выбрался к винде.. Что-то не то....
Код:

program sincos;
var x1,x2,y1,y2,a,b,c,cos,sin:real;
i:integer;
begin
x1:=0;
y1:=0;
x2:=100;
y2:=100;
a:=abs(trunc(x1-x2));//катит у
b:=abs(trunc(y1-y2));//катит х
c:=sqrt(a*a+b*b);//гипотенуза
cos:=b/c;//cosB
sin:=a/c;//sinB угол против стороны У
for i:=-2 to 2 do begin
x1:=x1+cos*i;//
y1:=y1+sin*i;//          Переносим точки, так
x2:=x2+cos*i;//                            чтобы линия была параллельна...
y2:=y2+sin*i;//
DrawLine(trunc(x1),trunc(y1),trunc(x2),trunc(y2));
end;
repaint;
delay(3000);
x1:=100;
y1:=100;
x2:=0;
y2:=100;
a:=abs(trunc(x1-x2));//катит у
b:=abs(trunc(y1-y2));//катит х
c:=sqrt(a*a+b*b);//гипотенуза
cos:=b/c;//cosB
sin:=a/c;//sinB угол против стороны У
for i:=-2 to 2 do begin
x1:=x1+cos*i;//
y1:=y1+sin*i;//          Переносим точки, так
x2:=x2+cos*i;//                            чтобы линия была параллельна...
y2:=y2+sin*i;//
DrawLine(trunc(x1),trunc(y1),trunc(x2),trunc(y2));
end;
repaint;
delay(3000);
x1:=0;
y1:=100;
x2:=50;
y2:=50;
a:=abs(trunc(x1-x2));//катит у
b:=abs(trunc(y1-y2));//катит х
c:=sqrt(a*a+b*b);//гипотенуза
cos:=b/c;//cosB
sin:=a/c;//sinB угол против стороны У
for i:=-2 to 2 do begin
x1:=x1+cos*i;//
y1:=y1+sin*i;//          Переносим точки, так
x2:=x2+cos*i;//                            чтобы линия была параллельна...
y2:=y2+sin*i;//
DrawLine(trunc(x1),trunc(y1),trunc(x2),trunc(y2));
end;
repaint;
delay(3000);
end;


Зато они параллельны! Это достижение)

cherepets 23.01.2010 16:51

Ответ: Ошибка синтаксиса.
 
VotapilD, nhal по wine работает.
в втк возможно эмуль входит, но яву я так и не смог поставить нормально(((

Tronix 23.01.2010 18:32

Ответ: Ошибка синтаксиса.
 
Вложений: 2
Не-не, sin/cos это все тормоза адовые. Да к тому-же еще и float-point. Щаз может полигонами запилю, будет как настоящая :)

UPD: Кое чего получается.... Осталось только код в порядок привести, или фиг с ним? )

Tronix 23.01.2010 20:36

Ответ: Ошибка синтаксиса.
 
Вложений: 2
Короче набросал вроде с помощью треугольников. Главный косяк - не помню вообще как найти точки ABCD (см рисунок). По обрывкам памяти и гуглу набросал, но чувствую что криво, што ппц.

Плюсы:
- быстро. В процедуре отрисовки треугольника только целочисленные числа. Единственное два деления на итерацию на inner_loop, но не критично.
- Когда вертикально или горизонтально - рисуем просто стандартным FillRect
- Когда ширина = 1 рисуем просто стандартно Line

Минусы:
- немного не точно, ибо либо с формулой точек ABCD косяк либо где-то чето не так округляется. Если не придираться - смотрица нормально.
- нельзя с помощью такого метода рисовать пунктирные линии например. Хотя с помощью небольшой допилки filltriangle можно. А если впилить простейшее текстурирование можно даже текстурами рисовать )))
Скриншоты всего этого безобразия выше.

Reizel 23.01.2010 20:42

Ответ: Ошибка синтаксиса.
 

Мой мозг никак не уймется. Автор, какая связь между названием темы и ее содержанием?? Может я что то не понимаю...

odd 23.01.2010 22:53

Ответ: Ошибка синтаксиса.
 
Что вы мучаетесь? Может мне легче библиотеку для рисования линии произвольной толщины написать? Будет работать немного быстрее и без глюков. Я вроде геометрию пока не всю забыл.

VotapilD 23.01.2010 23:02

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от Павел (Сообщение 134569)

Мой мозг никак не уймется. Автор, какая связь между названием темы и ее содержанием?? Может я что то не понимаю...

мне даже говорить стыдно...


Цитата:

Сообщение от Tronix
Короче набросал вроде с помощью треугольников. Главный косяк - не помню вообще как найти точки ABCD

Спасибо за идею, буду пробовать... Код какой-то странный, щас вот эмуль поставлю)

VotapilD 23.01.2010 23:03

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от odd (Сообщение 134581)
Что вы мучаетесь? Может мне легче библиотеку для рисования линии произвольной толщины написать? Будет работать немного быстрее и без глюков. Я вроде геометрию пока не всю забыл.

Давай)Я те вроде в ЛС писал))) Буду очень благодарен) И если можно, для вектора тоже)

Tronix 23.01.2010 23:16

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от odd (Сообщение 134581)
Что вы мучаетесь? Может мне легче библиотеку для рисования линии произвольной толщины написать? Будет работать немного быстрее и без глюков. Я вроде геометрию пока не всю забыл.

Да я собственно не мучаюсь, так просто время свободное было вот и предложил уже 2 варианта решения. Если первый смотрится конечно не очень (хотя мне нравятся острые концы у линии), то последний вполне себе кошерно выглядит на мой взгляд. Прям как во всяких модулях Graph турбопаскальных :) Кстати о каких именно глюках речь? В последнем варианте я их лично не наблюдаю.

Но если есть какие-то стандартные средства в яве, чтобы пилить толстые линии - то конечно проще сделать либу, чем так извращатся. :) Вообще будет полезная штука я думаю, особенно если с паттернами (прерывистая там, пунктирная и тд)

GRAY_WOLF 24.01.2010 10:59

Ответ: Ошибка синтаксиса.
 
Цитата:

Сообщение от odd (Сообщение 134581)
Что вы мучаетесь? Может мне легче библиотеку для рисования линии произвольной толщины написать? Будет работать немного быстрее и без глюков. Я вроде геометрию пока не всю забыл.

Еще бы и XML довел до ума, а то одни обрывки слов.

Tronix 24.01.2010 22:55

Ответ: Ошибка синтаксиса.
 
2odd: Кстати, погуглив понял, что из того самого 2DGraphics возможно установить только два типа линий: SOLID и DOTED. Как я понимаю, SOLID это толщина в 3 пикселя, причем скорее всего рисуют в самом классе по тому же Брезенхему, как plot(x-1,y); plot (x,y); plot(x+1,y) - особо не заморачиваясь. Могу ошибаться конечно, но что-то мне подсказывает....

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

Также начиная с MIDP2.0 есть вроде-как стандартная функция рисования закрашенных треугольников (UPD: ну да, например здесь уже пробегала в lib_gfx например). Можно мою процедуру fillrectangle заменить на нее, на MIDP2 будет наверно быстрее, с другой стороны на MIDP1 работать не будет вообще.

odd 25.01.2010 03:08

Ответ: Отрисовка толстых линий
 
MIDP 1.0 скоро уйдет в историю как и старые профили мидлетов (не даром я их назвал "Под старину"), так что не стоит особо бояться проблем с совместимостью.

VotapilD 25.01.2010 22:36

Ответ: Ошибка синтаксиса.
 
Вложений: 1
Вот вроде бы рабочий мой вариант:
Цитата:

Сообщение от VotapilD (Сообщение 134484)
Код:

program sincos;
var x1,x2,y1,y2,a,b,c,cos,sin:real;
i:integer;
begin
x1:=0;
y1:=0;
x2:=100;
y2:=100;
a:=abs(trunc(x1-x2));//катит у
b:=abs(trunc(y1-y2));//катит х
c:=sqrt(a*a+b*b);//гипотенуза
cos:=b/c;//cosB
sin:=a/c;//sinB угол против стороны У
for i:=-2 to 2 do begin
x1:=x1+cos+i;//
y1:=y1+sin+i;//          Переносим точки, так
x2:=x2+cos+i;//                            чтобы линия была параллельна...
y2:=y2+sin+i;//
DrawLine(trunc(x1),trunc(y1),trunc(x2),trunc(y2));
end;
repaint;
delay(3000);


Скрещение моей формулы и Tronixa в чём ошипка... Не могу найти.
АПД:Нужна библиотека Lib_gfx; А вообще, вот Все библиотеки(Вообще все)!

odd 26.01.2010 04:50

Ответ: Отрисовка толстых линий
 
Как доведете до блеска алгоритм, я его тогда реализую на Java в виде отдельной библиотеки. Без проблем. Или добавлю функцию рисования толстых линий в Lib_gfx.

VotapilD 26.01.2010 08:23

Ответ: Отрисовка толстых линий
 
Вложений: 1
Сегодня... Где-то в 2 часа ночи я закончил алгоритм. Вроде всё верно, фуууф...
ОНО РАБОТАЕТ!

Цитата:

Сообщение от odd (Сообщение 134783)
Как доведете до блеска алгоритм, я его тогда реализую на Java в виде отдельной библиотеки. Без проблем. Или добавлю функцию рисования толстых линий в Lib_gfx.

Посмотри, ещё сильней сжать алгоритм можно?)

odd 26.01.2010 13:36

Ответ: Отрисовка толстых линий
 
Нет, нормально. Больше вряд ли сожмется. Можно конвертировать в либу.
Ждите обновления библиотеки LIb_gfx

VotapilD 26.01.2010 15:08

Ответ: Отрисовка толстых линий
 
Можно ещё сильнее!(наверное)! xa,ya,xb и тд не надо делать реалом(Ставим Инт)!
после нахождения син и кос:

a:=abs(trunc(x1-x2));//катит у
b:=abs(trunc(y1-y2));//катит х
c:=(sqrt(a*a+b*b));//гипотенуза
cos:=(b/c);//cosB
sin:=(a/c);//sinB угол против стороны У
if (x2-x1<0)xor(y1-y2<0) then cos:=-cos;
cosadd:=trunc(cos*h);
sinadd:=trunc(sin*h);

xa:=x1+cosadd;//
ya:=y1+sinadd;// Переносим точки, так
xb:=x2+cosadd;// чтобы линия была параллельна...
...
...
FillTriangle(xa,ya,xb,yb,xc,yc);
FillTriangle(xc,yc,xd,yd,xb,yb);
end;

Но там баги с округлением(((

im_zorg 27.01.2010 19:35

Ответ: Отрисовка толстых линий
 
odd сделал скачай последьнюю версию lib_gfx

odd 27.01.2010 22:12

Ответ: Отрисовка толстых линий
 
Цитата:

Сообщение от im_zorg (Сообщение 134948)
odd сделал скачай последьнюю версию lib_gfx

Я там ещё немного упростил алгоритм. Попробуете округление, вроде бы получилось неплохо.

Tronix 27.01.2010 22:39

Ответ: Отрисовка толстых линий
 
Цитата:

Сообщение от odd (Сообщение 134973)
Я там ещё немного упростил алгоритм. Попробуете округление, вроде бы получилось неплохо.

Оооо, посмотрел исходник - значит моя формула верна все-таки. А я думал кривая она... Кстати, думаю там нужно вызывать M.G.filltriangle, а не filltriangle - а то получается функция drawline вызывает функцию filltriangle, которая вызывает filltriangle...

romby 20.11.2011 23:08

Ответ: Отрисовка толстых линий
 
А есть готовое решение для рисования линий со сглаженными краями (antialiasing)?

ВиНТ 27.02.2012 18:13

Ответ: Отрисовка толстых линий
 
Цитата:

Сообщение от impersonalis (Сообщение 133797)
рисуйте окружности. Радиус R - толщина линии. Над расстояниям - надо подумать..

садомазохизм :stop:

Однако надо не линиями пользоваться, а векторами(вершинами).
Если есть угол, то нужно его найти функцией atan2(y,x)! Вроде в MidletPascal 3.3 есть такая возможность. Так, ну ещё надо сделать вид центрирования это четырёхугольника(из векторов) - надо половину необходимой ширины отделить на каждую вершину разрывая углы на -90 и 90... Сложно.


Часовой пояс GMT +4, время: 06:20.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot