Hi there!

deco.text() has an angle attribute specifying the direction (with
respect to the coordinate system) in which to shift the text from the
point on the path. When annotating curves with multiple labels at points
with different slopes I find it more convenient to shift text along the
normal to the curve. I suggest making the default of the angle argument
"None" instead of 0, "None" meaning "use the direction of the normal".

An alternative would be to measure the angle with respect to the tangent
(maybe toggled by a boolean option "usetangent"), although I imagine
only ever using 90 and 270 degrees then.

I also noticed that deco.text() uses "relarclenpos" where deco.arrow()
uses "pos" with the same meaning. A common name would be useful.

I attached a deco.ttext() method implementing the changed default
behaviour (None=use normal). Text decorators are shifted perpendicularly
to the right of the path (to the left if textdist<0).
As it is it's meant to go into deco.py (uses the same imports etc.). I'd
be happy to provide a diff once I know whether deco.ttext() is supposed
to substitute the current deco.text(), complement it or just live in my
own module tree ;)

Cheers,
Michael

P.S.: This is inspired by the vector example!
class ttext(deco, attr.attr):
    """a simple text decorator with directed output"""

    def __init__(self, text, textattrs=[], angle=None, textdist=0.2,
                       relarclenpos=0.5, arclenfrombegin=None, 
arclenfromend=None,
                       texrunner=None):
        if arclenfrombegin is not None and arclenfromend is not None:
            raise ValueError("either set arclenfrombegin or arclenfromend")
        self.text = text
        self.textattrs = textattrs
        self.angle = angle
        self.textdist = textdist
        self.relarclenpos = relarclenpos
        self.arclenfrombegin = arclenfrombegin
        self.arclenfromend = arclenfromend
        self.texrunner = texrunner

    def decorate(self, dp, texrunner):
        if self.texrunner:
            texrunner = self.texrunner
        import text as textmodule
        textattrs = attr.mergeattrs([textmodule.halign.center, 
textmodule.vshift.mathaxis] + self.textattrs)

        dp.ensurenormpath()
        if self.arclenfrombegin is not None:
            textpos = dp.path.begin() + self.arclenfrombegin
        elif self.arclenfromend is not None:
            textpos = dp.path.end() - self.arclenfromend
        else:
            # relarcpos is used, when neither arcfrombegin nor arcfromend is 
given
            textpos = self.relarclenpos * dp.path.arclen()
        x, y = dp.path.at(textpos)
        if self.angle is None:
          dx, dy = dp.path.trafo(textpos).apply(0,-1) # compute normal - this 
is the endpoint of the vector based at x, y!
          dx, dy = unit.topt(dx-x), unit.topt(dy-y) # linealign doesn't like 
units in directions
        else:
          dx, dy = math.cos(self.angle*math.pi/180), 
math.sin(self.angle*math.pi/180)

        t = texrunner.text(x, y, self.text, textattrs)
        if self.textdist <0: # lienalign doesn't handle negative distances well
          t.linealign(-self.textdist, -dx, -dy)
        else:
          t.linealign(self.textdist, dx, dy)
        dp.ornaments.insert(t)

Reply via email to