Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vectorized Arrow Heads #6835

Closed
Tunnelvisie opened this issue Aug 29, 2017 · 3 comments · Fixed by #10788
Closed

Vectorized Arrow Heads #6835

Tunnelvisie opened this issue Aug 29, 2017 · 3 comments · Fixed by #10788

Comments

@Tunnelvisie
Copy link

I posted this in the Bokeh Gmail Group before and Bryan advised to open an issue. So here it is (better late then never):

See my sample code below. I'm drawing a whole bunch of arrows in a plot, all arrows have a line weight (lw), an alpha (a) and an arrow line weight (lw_arrow) -basically the arrow size- and start and end coordinates.

Unfortunately when I feed this information to my plot using source it seems impossible to send the 'a' and 'lw_arrow' into the VeeHead function, and it seems only possible to hard code the variables in VeeHead, as I have done now.

What I would like to do instead is the following: end=VeeHead(fill_color="black", size='lw_arrow', fill_alpha='a', line_alpha='a') where 'lw_arrow' and 'a' are coming from source.

from bokeh.plotting import figure
from bokeh.models import Arrow, VeeHead
from bokeh.models import ColumnDataSource
import pandas as pd
from bokeh.io import curdoc

df = pd.DataFrame(
    {'x1': [48.61416189, 50.76303746, 47.54218554, 46.91226294],
     'y1': [78.99324704, 80.69915616, 79.41805739, 80.28060694],
     'x2': [70.60720053, 67.54310965, 52.38867755, 34.25213619],
     'y2': [52.90955905, 93.23068347, 37.70820205, 52.30176102],
     'lw': [5, 6, 7, 2],
     'a': [1, 1, 0.5, 0.25],
     'lw_arrow': [15, 18, 21, 6],

    })

p = figure(plot_width=600, plot_height=428,
               x_range=[0,100],
               y_range=[0,100],
               logo=None,
               toolbar_location = 'below')


source = ColumnDataSource(data=dict(
        x1=[],
        y1=[],
        x2=[],
        y2=[],
        lw=[],
        a=[],
        lw_arrow=[],

    ))

arrows = Arrow(end=VeeHead(fill_color="black", size=10, fill_alpha=.5, line_alpha=.5),
                   x_start='x1',
                   y_start='y1',
                   x_end='x2',
                   y_end='y2',
                   source=source,
                   line_width='lw',
                   line_alpha='a')

p.add_layout(arrows)

def update():
    """
    update the new graph with the values from selected at select_for_graph by passing it through the source
    :return:
    """

    #for the lines we need the whole dataframe
    source.data = dict(
        x1=df['x1'],
        y1=df['y1'],
        x2=df['x2'],
        y2=df['y2'],
        lw=df['lw'],
        a=df['a'],
        lw_arrow=df['lw_arrow']
    )

curdoc().add_root(p)
curdoc().add_periodic_callback(update,1000)
@bryevdv
Copy link
Member

bryevdv commented Aug 30, 2017

I think vectorizing Arrow is not unreasonable. I am not sure about vectorizing arrow heads by themselves. We could either add a source to existing Arrow, ala Span, or go the route of LabelSet and make ArrowSet. Regrettably things are not completely consistent within Bokeh annotations on this point. Thoughts @bokeh/dev ?

@mattpap
Copy link
Contributor

mattpap commented Aug 30, 2017

I think vectorizing Arrow is not unreasonable.

Arrow is already vectorized, contrary to Label, which requires LabelSet for that purpose. It's only arrow heads that could be vectorized as well. Though I'm not sure how, because vectorizing Instance properties doesn't seem feasible. We would have to vectorize properties of arrow heads and connect those to arrow's data source. This isn't that far from what we do with glyphs and glyph renderers.

However, speaking about vectorization and arrows, I would like to put once again the idea under consideration of making arrows glyphs.

@Tunnelvisie
Copy link
Author

I'd like to add that currently I'm using standard lines and triangle glyphs to simulate a similar result.

Biggest problems with this is the fact that the triangles instigate from the center instead of from the end of the line. This means that I would have to 'manually' correct the length of every line to reduce it by half the arrows height in order for it to end in the same position as Arrow. This same problem might occur if you add arrow heads as glyphs. Second problem with this is overlapping of both glyphs creating uneven colours when using an alpha != 1.

If at all possible adding arrows as glyphs seems like a fair solution to me? Though it would obviously need separate sizing options for head and line width etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants