On Fri, May 15, 2015 at 10:53 AM, Thomas Caswell <[email protected]> wrote:
> A few very quick comments (just skimmed the docstrings)
>
> We already have a mpl.path.Path class, please don't shadow that.
>
I read the Path class and based mine on that. The problem is that I want
to be able to place nodes along the path (like labels) and so I need to ask
it questions. Maybe we should just extend the existing Path class? Or
else we should call my Path something different?
> Is your `Path` going to be an `Artist` that is responsible for drawing
> it's self or does in serve a role like the existing `Path` in that it is
> used by other artists as part of their `draw`?
>
> This feels very similar to the `FancyArrow` (with classes being passed in
> to control how the arrow is styled), would this make sense as an extension
> to that code? This does seem more general, maybe it makes sense to start
> from scratch and implement `FancyArrow` in terms of this code.
>
Yes! Didn't know about that. I think modifying and extending that code
might be a good way forward.
>
> Tom
>
> On Fri, May 15, 2015 at 10:40 AM Neil Girdhar <[email protected]>
> wrote:
>
>> I have a draft proposal of the long term goal for what an interface could
>> look like for drawing arrows between coordinates or nodes. I based the
>> design on the tikz manual (http://pgf.sourceforge.net/pgf_CVS.pdf), so
>> it might help to flip through that to get an idea for the basis of this
>> design. I tried to separate the creating of Path objects with the drawing
>> of paths since it's often really useful when compositing layouts to be able
>> to do math with with the positions of things before drawing anything. For
>> example, when automatically positioning nodes.
>>
>> I'm not committed to this design; it's just an outline to get feedback.
>>
>> Best,
>>
>> Neil
>>
>> class Axes_(_AxesBase):
>> def path(self, path, draw=True, fill=False):
>> """
>> If draw is not falsy, draws along the path using the draw
>> specification.
>> If fill is not falsy, fills the closed path using the fill
>> specification.
>>
>> Parameters
>> ----------
>> path is a Path object or path commands with which to create one.
>>
>> draw is a draw specification:
>> either the value True, which indicates some defaults, or else
>> False, or else a dictionary with the following keys:
>> color
>> opacity
>> line_width
>> line_join
>> begin_tip is a Tip object
>> tip or end_tip is a Tip object
>> dashed is a dash specification
>>
>> a dash specification
>> either dictionary containing:
>> dash_pattern
>> an iterable of numbers specifying the length of the
>> dashes
>> and gaps in points. E.g., [2, 3, 4, 3] means on for 2
>> points, off for 3, on for 4, off for 3, i.e.,
>> dash-dotted.
>> dash_phase
>> Shifts the start of the dash pattern by dash_phase
>> points.
>> or a string, one of:
>> 'solid'
>> 'dotted', 'densely dotted', 'loosely dotted'
>> 'dashed', 'densely dashed', 'loosely dashed'
>> 'dash dot', 'densely dash dot', 'loosely dash dot'
>> 'dash dot dot', 'densely dash dot dot', 'loosely dash dot
>> dot'
>>
>> fill is a fill specification:
>> TODO
>> """
>>
>> class Path:
>> def __init__(self, path_commands):
>> """
>> path_commands is either
>> a coordinate (representing a move to in the first position,
>> or a
>> line to in any other position)
>> MoveTo(coordinate)
>> LineTo(coordinate_or_node, draw=None)
>> CurveTo(coordinate_or_node, control_points, draw=None)
>> ClosePolygon()
>>
>> optional draw commands override the draw specification of the
>> whole
>> path within that edge.
>>
>> a coordinate is either an (x, y) pair, or a Coordinate object.
>> a node is a Node object.
>> """
>>
>> def at_position(self, fraction=0.5):
>> """
>> Returns a coordinate fraction of the way along the line.
>> fraction can be one of 'at end', 'very near end', 'near end',
>> 'midway', 'near start', 'very near start', 'at start'
>> """
>>
>> def node_at(node, fraction=0.5, location, ...)
>> """
>> Sets the node's position so that it sits flush to the path.
>>
>> Parameters
>> ----------
>> location :
>> Could be 'above', 'below', 'on', or a number, which is the
>> number
>> of points away from the path to place the node.
>> """
>>
>> def pin_node(node, pin_distance, draw=draw_specification):
>> pass
>>
>>
>> class Coordinate:
>> @property
>> def coordinate(self):
>> return (self.x, self.y)
>>
>> def node_at(self, node, angle):
>> """
>> Places the node so that it is in the direction angle from the
>> coordinate. E.g.,
>> angle=pi/2, or angle='above' places the node so that the
>> coordinate is
>> touching the center-bottom of the node.
>> angle could be 'above', 'below', 'left', 'right', 'above left',
>> etc.
>> """
>>
>> class Node:
>> """
>> Available Node objects:
>> Rectangle, Circle
>> """
>> @property
>> def center(self):
>> return (self.x, self.y)
>>
>> def node_at(self, node, angle):
>> """
>> Places the node so that it is in the direction angle from the
>> coordinate. The node could be an arrowhead for example.
>> """
>>
>> def convex_hulls(self):
>> """
>> Returns a list of convex hulls. The convex hulls are used when
>> position one node or arrowhead flush with another using the
>> separating axis algorithm.
>> """
>>
>> class Tip:
>> """
>> Available Tip objects:
>> ButtCap (no tip, the default)
>> RectangleCap, TriangleCap, RoundCap
>> ArcBarb, Bar, Bracket, Hooks, Parenthesis,
>> StraightBarb, TeeBarb
>> Circle, Diamond, Ellipse, Kite, Arrow,
>> Rectangle, Square, Stealth, Triangle,
>> TurnedSquare
>> TipCombination (accepts multiple tips and merges them)
>> """
>> def __init__(self, draw=None, fill=True, reversed_=False):
>> pass
>>
>> def convex_hulls(self, line_width):
>> """
>> Returns a list of convex hulls for use with placement
>> whereby the arrow faces right starting at the origin.
>> """
>>
>> def transmute(self, line_width):
>> """
>> Returns a pair of lists (draw_path, fill_path).
>> """
>>
>> @property
>> def draw_specification(self):
>> """
>> is a draw specification, or None to use the parent line's
>> """
>> def fill_specification(self):
>> """
>> Is a fill specification, or True to use defaults based
>> on the parent line's draw color, or False to use an open fill.
>> """
>>
>> -----
>>
>> Usage:
>>
>> # draw an arrow from point to point.
>> ax.path([(x, y), (x2, y2)], draw={'tip': Arrow()})
>>
>> # Create a path.
>> p = Path([(x, y), (x2, y2)])
>>
>> # Create a node along the path.
>> n = p.node_at(Label("some label"))
>>
>> # Draw the path using an arrow, and the node.
>> ax.path(p, draw={'tip': Arrow()})
>> ax.node(n)
>>
>>
>> On Wed, May 13, 2015 at 11:27 PM, Thomas Caswell <[email protected]>
>> wrote:
>>
>>> Sorry, I may have been being a bit dramatic
>>>
>>> In mpl.patches: Arrow, FancyArrow, YAArrow, FancyArrowPatch,
>>> ConnectionPatch + annotation related artists + some classes in axisartist
>>> which now that I look at them are not really general purpose arrow tools.
>>> I had not been counting quiver (or barbs) or sankey.
>>>
>>> Neil: Those are all great questions! Much of the arrow related code was
>>> written by Joe-Joon Lee who (by having read a good deal of his code) has a
>>> habit of writing very power but very opaque python.
>>>
>>> I believe that the line join style is controlled by `joinstyle` on the
>>> graphics context and it is up to the backends to implement that correctly.
>>>
>>> Tom
>>>
>> On Wed, May 13, 2015 at 10:58 PM Neil Girdhar <[email protected]>
>>> wrote:
>>>
>> Okay, I'm looking at this in more detail and there may be some design
>>>> concerns:
>>>>
>>>> The arrow placement is decided without asking the arrow any questions,
>>>> such as its bounding box. Instead, the arrow should return a bounding box
>>>> and then the line should retreat until the bounding box no longer
>>>> intersects the target node. Then the arrow should be placed. This doesn't
>>>> matter so much when you have a simple arrow like this: ---->, but it's a
>>>> big deal when you have an arrow like ----| . In this case, the sides of
>>>> the arrow risk intersecting with the target node.
>>>>
>>>> I'm not keen on implementing every arrow three times: <-, ->, <->.
>>>> This really should be handled by the code placing the arrows for many
>>>> reasons:
>>>> 1. It should also be possible to have a different arrowhead at either
>>>> end of the line.
>>>> 2. It should be possible to stack the arrows, for example having two
>>>> heads one after another (to represent two kinds of relationships). This is
>>>> another reason to be able to ask the arrowhead its length and so on.
>>>>
>>>> I don't understand the "monolithic" keyword. How can the arrow draw
>>>> the line as well when it doesn't know the line style, color and so on?
>>>>
>>>> I think I like the design of the transmute function. I'm curious:
>>>> ultimately, where does the mutation_size come from? Is it a global scale
>>>> applied to the figure, or is it based on the linewidth, or?
>>>>
>>>> When you emit a set of lines, how are they joined? If I draw a line
>>>> having linewidth 0.1 from the origin to (1, 0), and back to (0, 0.5), what
>>>> happens at the tip? Are two rectangles drawn (each having width 0.1, but
>>>> oriented differently)? Is a bevel created? A miter? Or is the tip
>>>> rounded? Can this be controlled? See page 166 of the manual I sent
>>>> earlier (search for tikz/line join).
>>>>
>>>> Best,
>>>>
>>>> Neil
>>>>
>>> On Wed, May 13, 2015 at 10:14 PM, Neil Girdhar <[email protected]>
>>>> wrote:
>>>>
>>> Thanks, it works!
>>>>>
>>>>> I needed to add:
>>>>>
>>>>> import matplotlib.patches
>>>>>
>>>>> to one file and
>>>>>
>>>>> plt.show()
>>>>>
>>>>> to the other.
>>>>>
>>>>> Any word on the locations in the code of the seven arrow drawing
>>>>> methods?
>>>>>
>>>>> I've located the arrow drawing code in tikz, and so I can start
>>>>> porting it over. I'm curious, do we know the linewidth of the edge being
>>>>> decorated by the arrow? To make arrows scale nicely, most of the arrow
>>>>> dimensions are given in two pieces: an absolute value (in points for
>>>>> example) and a line width factor. The dimension is the absolute value
>>>>> plus
>>>>> the line width factor times the line width. The TikZ manual explains:
>>>>> "This makes it easy to vary the size of an arrow tip in accordance with
>>>>> the
>>>>> line width – usually a very good idea since thicker lines will need
>>>>> thicker
>>>>> arrow tips."
>>>>>
>>>>> Best,
>>>>>
>>>>> Neil
>>>>>
>>>> On Wed, May 13, 2015 at 10:07 PM, Benjamin Reedlunn <[email protected]
>>>>> > wrote:
>>>>>
>>>> Neil,
>>>>>>
>>>>>> I have attached code to draw the arrowhead.
>>>>>>
>>>>>> -Ben
>>>>>>
>>>>>>
>>>>>> On May 13, 2015, at 7:44 PM, Neil Girdhar <[email protected]>
>>>>>> wrote:
>>>>>>
>>>>>> Do you have the code that you used to draw the arrowhead? I'm up to
>>>>>> date now on the development workflow (
>>>>>> http://matplotlib.org/devel/gitwash/development_workflow.html), so
>>>>>> I'm ready to start working.
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Neil
>>>>>>
>>>>>> On Wed, May 13, 2015 at 9:10 PM, Benjamin Reedlunn <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>> Yes, I fully agree that we need to unify the many different ways to
>>>>>>> draw arrows.
>>>>>>>
>>>>>>> Neil, in case an example would be helpful for you, I have attached a
>>>>>>> module that includes a custom arrowhead class. The arrowhead class
>>>>>>> works
>>>>>>> with the with the ax.annotate() method. (I like the annotate method
>>>>>>> because it allows me to easily mix and match coordinate systems for
>>>>>>> arrow
>>>>>>> placement.) As you can see in the attached pdf, the custom arrowhead
>>>>>>> doesn't include fancy Bezier curves, but that could be added.
>>>>>>>
>>>>>>> -Ben
>>>>>>>
>>>>>>>
>>>>>>> On May 13, 2015, at 2:54 PM, Thomas Caswell <[email protected]>
>>>>>>> wrote:
>>>>>>>
>>>>>>> The other thing that should be done is to unify the (I think 7?!?)
>>>>>>> unique ways to draw arrows in mpl.
>>>>>>>
>>>>>>> On Wed, May 13, 2015 at 4:52 PM Neil Girdhar <[email protected]>
>>>>>>> wrote:
>>>>>>>
>>>>>>> Yes, I just noticed that as well. That's how the tikz pgf code
>>>>>>>> looks (a sequence of line_to and curve_to commands and so on) so it
>>>>>>>> should
>>>>>>>> be easy to port over the various shapes.
>>>>>>>>
>>>>>>>> On Wed, May 13, 2015 at 4:49 PM, Eric Firing <[email protected]>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> On 2015/05/13 10:12 AM, Neil Girdhar wrote:
>>>>>>>>>
>>>>>>>>>> If you want to make arrowheads look at all decent, they really
>>>>>>>>>> need to
>>>>>>>>>> be enclosed in Bezier curves. See the diagram here:
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Mpl paths support Bezier curves.
>>>>>>>>> http://matplotlib.org/api/path_api.html?highlight=bezier
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> http://tex.stackexchange.com/questions/150289/how-do-you-accomplish-stealth-with-the-new-arrows-meta/230965#230965
>>>>>>>>>>
>>>>>>>>>> The first two look like garbage. The last one is the only one
>>>>>>>>>> that
>>>>>>>>>> looks good imho.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> That depends on the application, and the observer.
>>>>>>>>
>>>>>>>>
>>>>>>>> Sure, but I may as well port them all of the tikz arrowheads over
>>>>>>>> since most of the work would be figuring out how to do it.
>>>>>>>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Eric
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> Best,
>>>>>>>>>>
>>>>>>>>>> Neil
>>>>>>>>>>
>>>>>>>>>> On Wed, May 13, 2015 at 4:09 PM, Eric Firing <[email protected]
>>>>>>>>>> <mailto:[email protected]>> wrote:
>>>>>>>>>>
>>>>>>>>>> On 2015/05/13 9:36 AM, Neil Girdhar wrote:
>>>>>>>>>>
>>>>>>>>>> I don't know matplotlib well enough (yet) to know what the
>>>>>>>>>> change would
>>>>>>>>>> consist of.
>>>>>>>>>>
>>>>>>>>>> I suggest you take a look at the beautiful tikz manual:
>>>>>>>>>> http://pgf.sourceforge.net/pgf_CVS.pdf
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Very helpful, thank you.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The arrows.meta on page 201–212 are really well-designed
>>>>>>>>>> and
>>>>>>>>>> beautiful.
>>>>>>>>>>
>>>>>>>>>> Compare this with matplotlib's custom arrows:
>>>>>>>>>>
>>>>>>>>>> http://stackoverflow.com/questions/16968007/custom-arrow-style-for-matplotlib-pyplot-annotate
>>>>>>>>>>
>>>>>>>>>> How do I make tikz's arrowheads available for all
>>>>>>>>>> backends?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> My guess offhand is that this is a matter of using the mpl
>>>>>>>>>> API. I
>>>>>>>>>> don't think we would want to add all of these types and
>>>>>>>>>> options to
>>>>>>>>>> the mpl core; but a toolkit might be ideal for this. The mpl
>>>>>>>>>> API,
>>>>>>>>>> which generates the same results for all backends, is quite
>>>>>>>>>> complete
>>>>>>>>>> and flexible. Things like arrowheads are Patch objects, and
>>>>>>>>>> you can
>>>>>>>>>> specify any path you want. The main trick is figuring out
>>>>>>>>>> how to
>>>>>>>>>> handle transforms--what kind of coordinates should the path be
>>>>>>>>>> specifying? How should things scale as a figure is reshaped
>>>>>>>>>> and
>>>>>>>>>> resized?
>>>>>>>>>>
>>>>>>>>>> For many of these types you could also use mpl Line2D
>>>>>>>>>> objects, for
>>>>>>>>>> which several properties including cap style can be
>>>>>>>>>> specified. Not
>>>>>>>>>> all of the TikZ options would be available, but perhaps
>>>>>>>>>> enough.
>>>>>>>>>>
>>>>>>>>>> Eric
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>> ------------------------------------------------------------------------------
>>>>>>>> One dashboard for servers and applications across
>>>>>>>> Physical-Virtual-Cloud
>>>>>>>> Widest out-of-the-box monitoring support with 50+ applications
>>>>>>>> Performance metrics, stats and reports that give you Actionable
>>>>>>>> Insights
>>>>>>>> Deep dive visibility with transaction tracing using APM Insight.
>>>>>>>>
>>>>>>> _______________________________________________
>>>>>>>> Matplotlib-devel mailing list
>>>>>>>> [email protected]
>>>>>>>> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
>>>>>>>>
>>>>>>>
>>>>>>> ------------------------------------------------------------------------------
>>>>>>> One dashboard for servers and applications across
>>>>>>> Physical-Virtual-Cloud
>>>>>>> Widest out-of-the-box monitoring support with 50+ applications
>>>>>>> Performance metrics, stats and reports that give you Actionable
>>>>>>> Insights
>>>>>>> Deep dive visibility with transaction tracing using APM Insight.
>>>>>>>
>>>>>>> Matplotlib-devel mailing list
>>>>>>> [email protected]
>>>>>>> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>
>
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
Matplotlib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel