From d378597c30bcdacfc0d440d9b8d9e4224ac1f54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Sat, 14 May 2016 21:45:08 +0200 Subject: egd: Add line thickness algorithm for lines --- lib/percept/src/egd_primitives.erl | 10 ++---- lib/percept/src/egd_render.erl | 67 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 9 deletions(-) (limited to 'lib/percept/src') diff --git a/lib/percept/src/egd_primitives.erl b/lib/percept/src/egd_primitives.erl index 388446cc15..b64189c552 100644 --- a/lib/percept/src/egd_primitives.erl +++ b/lib/percept/src/egd_primitives.erl @@ -71,15 +71,11 @@ object_info(O) -> %% interface functions line(#image{objects=Os}=I, Sp, Ep, Color) -> - I#image{objects=[#image_object{ - type = line, - points = [Sp, Ep], - span = span([Sp, Ep]), - color = Color}|Os]}. + line(#image{objects=Os}=I, Sp, Ep, 1, Color). -line(#image{objects=Os}=I, Sp, Ep, Stroke, Color) -> +line(#image{objects=Os}=I, Sp, Ep, Wd, Color) -> I#image{objects=[#image_object{ - internals = Stroke, + internals = Wd, type = line, points = [Sp, Ep], span = span([Sp, Ep]), diff --git a/lib/percept/src/egd_render.erl b/lib/percept/src/egd_render.erl index 05059b526e..a97bb05cac 100644 --- a/lib/percept/src/egd_render.erl +++ b/lib/percept/src/egd_render.erl @@ -27,6 +27,9 @@ -export([eps/1]). -compile(inline). +-export([line_to_linespans/3]). +-export([line_ls/2]). + -include("egd.hrl"). -define('DummyC',0). @@ -315,8 +318,8 @@ precompile(#image{objects = Os}=I) -> I#image{objects = precompile_objects(Os)}. precompile_objects([]) -> []; -precompile_objects([#image_object{type=line, points=[P0,P1]}=O|Os]) -> - [O#image_object{intervals = linespans_to_map(line_ls(P0,P1))}|precompile_objects(Os)]; +precompile_objects([#image_object{type=line, internals=W, points=[P0,P1]}=O|Os]) -> + [O#image_object{intervals = linespans_to_map(line_to_linespans(P0,P1,W))}|precompile_objects(Os)]; precompile_objects([#image_object{type=filled_triangle, points=[P0,P1,P2]}=O|Os]) -> [O#image_object{intervals = triangle_ls(P0,P1,P2)}|precompile_objects(Os)]; precompile_objects([#image_object{type=polygon, points=Pts}=O|Os]) -> @@ -568,6 +571,66 @@ line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, true = Steep, LSs) when X =< X1 -> line_ls_step(_X,_,_Y,_Dx,_Dy,_Ys,_E,_X0,_,LSs) -> LSs. + + +%% line_to_linespans +%% Anti-aliased thick line +%% Do it CPS style +%% In: +%% P1 :: point() +%% P2 :: point() +%% Out: +%% [{Y,Xl,Xr}] +%% +line_to_linespans({X0,Y0},{X1,Y1},Wd) -> + Dx = abs(X1-X0), + Dy = abs(Y1-Y0), + Sx = if X0 < X1 -> 1; true -> -1 end, + Sy = if Y0 < Y1 -> 1; true -> -1 end, + E0 = Dx - Dy, + Ed = if Dx + Dy =:= 0 -> 1; true -> math:sqrt(Dx*Dx + Dy*Dy) end, + line_to_ls(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E0,Ed,(Wd+1)/2,[]). + +line_to_ls(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0) -> + %C = max(0, 255*(abs(E - Dx+Dy)/Ed - Wd + 1)), + %Ls1 = [{ls,Y0,X0,C}|Ls0], + Ls1 = [{Y0,X0,X0}|Ls0], + line_to_ls_sx(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls1,E). + +line_to_ls_sx(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2) when 2*E2 > -Dx -> + line_to_ls_sx_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2+Dy,Y0); +line_to_ls_sx(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2) -> + line_to_ls_sy(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2,X0). + +line_to_ls_sx_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,E2,Y) when E2 < Ed*Wd andalso + (Y1 =/= Y orelse Dx > Dy) -> + Y2 = Y + Sy, + %C = max(0,255*(abs(E2)/Ed-Wd+1)), + %Ls = [{sx,Y2,X0,C}|Ls0], + Ls = [{Y2,X0,X0}|Ls0], + line_to_ls_sx_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2+Dx,Y2); +line_to_ls_sx_do(X0,_Y0,X1,_Y1,_Dx,_Dy,_Sx,_Sy,_E,_Ed,_Wd,Ls,_E2,_Y) when X0 =:= X1 -> + Ls; +line_to_ls_sx_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,_E2,_Y) -> + line_to_ls_sy(X0+Sx,Y0,X1,Y1,Dx,Dy,Sx,Sy,E-Dy,Ed,Wd,Ls,E,X0). + +line_to_ls_sy(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,E2,X) when 2*E2 =< Dy -> + line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,Dx-E2,X); +line_to_ls_sy(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,_E2,_X) -> + line_to_ls(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0). + +line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,E2,X) when E2 < Ed*Wd andalso + (X1 =/= X orelse Dx < Dy) -> + X2 = X + Sx, + %C = max(0,255*(abs(E2)/Ed-Wd+1)), + %Ls = [{sy,Y0,X2,C}|Ls0], + Ls = [{Y0,X2,X2}|Ls0], + line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2+Dy,X2); +line_to_ls_sy_do(_X0,Y0,_X1,Y1,_Dx,_Dy,_Sx,_Sy,_E,_Ed,_Wd,Ls,_E2,_X) when Y0 =:= Y1 -> + Ls; +line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,_E2,_X) -> + line_to_ls(X0,Y0+Sy,X1,Y1,Dx,Dy,Sx,Sy,E+Dx,Ed,Wd,Ls). + % Text text_horizontal_ls(Point, Font, Chars) -> -- cgit v1.2.3