Ejemplo n.º 1
0
def dist_point_to_segment(p, s0, s1):
    """
    get the distance of a point to a segment.

    p, s0, s1 are xy sequences

    This algorithm from
    http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm#Distance%20to%20Ray%20or%20Segment
    """
    p = asarray(p, Float)
    s0 = asarray(s0, Float)
    s1 = asarray(s1, Float)    
    v = s1 - s0
    w = p - s0

    c1 = dot(w,v);
    if ( c1 <= 0 ):
        return dist(p, s0);

    c2 = dot(v,v)
    if ( c2 <= c1 ):
        return dist(p, s1);

    b = c1 / c2
    pb = s0 + b * v;
    return dist(p, pb)
Ejemplo n.º 2
0
    def get_rotation_matrix(self, x0, y0):

        theta = pi/180.0*self.get_rotation()
        # translate x0,y0 to origin
        Torigin = array([ [1, 0, -x0],
                           [0, 1, -y0],
                           [0, 0, 1  ]]) 
        
        # rotate by theta
        R = array([ [cos(theta),  -sin(theta), 0],
                     [sin(theta), cos(theta), 0],
                     [0,           0,          1]]) 

        # translate origin back to x0,y0
        Tback = array([ [1, 0, x0],
                         [0, 1, y0],
                         [0, 0, 1  ]]) 


        return dot(dot(Tback,R), Torigin)
Ejemplo n.º 3
0
    def get_rotation_matrix(self, x0, y0):

        theta = pi/180.0*self.get_rotation()
        # translate x0,y0 to origin
        Torigin = array([ [1, 0, -x0],
                           [0, 1, -y0],
                           [0, 0, 1  ]])

        # rotate by theta
        R = array([ [cos(theta),  -sin(theta), 0],
                     [sin(theta), cos(theta), 0],
                     [0,           0,          1]])

        # translate origin back to x0,y0
        Tback = array([ [1, 0, x0],
                         [0, 1, y0],
                         [0, 0, 1  ]])


        return dot(dot(Tback,R), Torigin)
Ejemplo n.º 4
0
    def plot_surface(self, X, Y, Z, *args, **kwargs):
        had_data = self.has_data()

        rows, cols = Z.shape
        tX,tY,tZ = nx.transpose(X), nx.transpose(Y), nx.transpose(Z)
        rstride = cbook.popd(kwargs, 'rstride', 10)
        cstride = cbook.popd(kwargs, 'cstride', 10)
        #
        polys = []
        boxes = []
        for rs in nx.arange(0,rows,rstride):
            for cs in nx.arange(0,cols,cstride):
                ps = []
                corners = []
                for a,ta in [(X,tX),(Y,tY),(Z,tZ)]:
                    ztop = a[rs][cs:min(cols-1,cs+cstride)]
                    zleft = ta[min(cols-1,cs+cstride)][rs:min(rows,rs+rstride+1)]
                    zbase = a[min(rows-1,rs+rstride)][cs:min(cols,cs+cstride+1):]
                    zbase = zbase[::-1]
                    zright = ta[cs][rs:min(rows-1,rs+rstride):]
                    zright = zright[::-1]
                    corners.append([ztop[0],ztop[-1],zbase[0],zbase[-1]])
                    z = nx.concatenate((ztop,zleft,zbase,zright))
                    ps.append(z)
                boxes.append(map(nx.array,zip(*corners)))
                polys.append(zip(*ps))
        #
        lines = []
        shade = []
        for box in boxes:
            n = proj3d.cross(box[0]-box[1],
                         box[0]-box[2])
            n = n/proj3d.mod(n)*5
            shade.append(nx.dot(n,[-1,-1,0.5]))
            lines.append((box[0],n+box[0]))
        #
        color = nx.array([0,0,1,1])
        norm = normalize(min(shade),max(shade))
        colors = [color * (0.5+norm(v)*0.5) for v in shade]
        for c in colors: c[3] = 1
        polyc = art3d.Poly3DCollection(polys, facecolors=colors, *args, **kwargs)
        polyc._zsort = 1
        self.add_collection(polyc)
        #
        self.auto_scale_xyz(X,Y,Z, had_data)
        return polyc
Ejemplo n.º 5
0
    def _get_layout(self, renderer):

        # layout the xylocs in display coords as if angle = zero and
        # then rotate them around self._x, self._y
        
        key = self.get_prop_tup()
        if self.cached.has_key(key): return self.cached[key]
        
        horizLayout = []
        pad =2
        thisx, thisy = self._transform.xy_tup( (self._x, self._y) )
        width = 0
        height = 0

        xmin, ymin = thisx, thisy
        if self.is_math_text():
            lines = [self._text]
        else:
            lines = self._text.split('\n')

        whs = []
        for line in lines:
            w,h = renderer.get_text_width_height(
                line, self._fontproperties, ismath=self.is_math_text())
            if not len(line) and not self.is_math_text():
                # approx the height of empty line with tall char
                tmp, h = renderer.get_text_width_height(
                'T', self._fontproperties, ismath=False)

            whs.append( (w,h) )
            offsety = h+pad
            horizLayout.append((line, thisx, thisy, w, h))
            thisy -= offsety  # now translate down by text height, window coords
            width = max(width, w)
        
        ymin = horizLayout[-1][2]
        ymax = horizLayout[0][2] + horizLayout[0][-1]
        height = ymax-ymin

        xmax = xmin + width
        # get the rotation matrix
        M = self.get_rotation_matrix(xmin, ymin) 

        # the corners of the unrotated bounding box
        cornersHoriz = ( (xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin) )                
        offsetLayout = []
        # now offset the individual text lines within the box
        if len(lines)>1: # do the multiline aligment
            malign = self._get_multialignment()
            for line, thisx, thisy, w, h in horizLayout:
                if malign=='center': offsetx = width/2.0-w/2.0
                elif malign=='right': offsetx = width-w
                else: offsetx = 0
                thisx += offsetx
                offsetLayout.append( (thisx, thisy ))
        else: # no additional layout needed
            offsetLayout = [ (thisx, thisy) for line, thisx, thisy, w, h in horizLayout]

        # now rotate the bbox
        
        cornersRotated = [dot(M,array([[thisx],[thisy],[1]])) for thisx, thisy in cornersHoriz]

        txs = [float(v[0][0]) for v in cornersRotated]
        tys = [float(v[1][0]) for v in cornersRotated]

        # compute the bounds of the rotated box
        xmin, xmax = min(txs), max(txs)
        ymin, ymax = min(tys), max(tys)
        width  = xmax - xmin
        height = ymax - ymin

        # Now move the box to the targe position offset the display bbox by alignment
        halign = self._horizontalalignment
        valign = self._verticalalignment        

        # compute the text location in display coords and the offsets
        # necessary to align the bbox with that location
        tx, ty = self._transform.xy_tup( (self._x, self._y) )
        
        if halign=='center':  offsetx = tx - (xmin + width/2.0)
        elif halign=='right': offsetx = tx - (xmin + width)
        else: offsetx = tx - xmin

        if valign=='center': offsety = ty - (ymin + height/2.0)
        elif valign=='top': offsety  = ty - (ymin + height)
        else: offsety = ty - ymin

        xmin += offsetx
        xmax += offsetx
        ymin += offsety
        ymax += offsety

        bbox = lbwh_to_bbox(xmin, ymin, width, height)

        
        # now rotate the positions around the first x,y position
        xys = [dot(M,array([[thisx],[thisy],[1]])) for thisx, thisy in offsetLayout]


        tx = [float(v[0][0])+offsetx for v in xys]
        ty = [float(v[1][0])+offsety for v in xys]

        # now inverse transform back to data coords
        xys = [self._transform.inverse_xy_tup( xy ) for xy in zip(tx, ty)]

        xs, ys = zip(*xys)

        ret = bbox, zip(lines, whs, xs, ys)
        self.cached[key] = ret
        return ret
Ejemplo n.º 6
0
def _norm(x):
    "return sqrt(x dot x)"
    return numerix.mlab.sqrt(dot(x,x))
Ejemplo n.º 7
0
def dist(x,y):
    'return the distance between two points'
    d = x-y
    return numerix.mlab.sqrt(dot(d,d))
Ejemplo n.º 8
0
    def update_coords(self, renderer):
        """Computes the actual x,y coordinates for
        text based on the input x,y and the
        dashlength. Since the rotation is with respect
        to the actual canvas's coordinates we need to
        map back and forth.
        """
        dashx, dashy = self.get_position()
        dashlength = self.get_dashlength()
        # Shortcircuit this process if we don't have a dash
        if dashlength == 0.0:
            self._x, self._y = dashx, dashy
            return

        dashrotation = self.get_dashrotation()
        dashdirection = self.get_dashdirection()
        dashpad = self.get_dashpad()
        dashpush = self.get_dashpush()

        angle = get_rotation(dashrotation)
        theta = pi * (angle / 180.0 + dashdirection - 1)
        cos_theta, sin_theta = cos(theta), sin(theta)

        transform = self.get_transform()

        # Compute the dash end points
        # The 'c' prefix is for canvas coordinates
        cxy = array(transform.xy_tup((dashx, dashy)))
        cd = array([cos_theta, sin_theta])
        c1 = cxy + dashpush * cd
        c2 = cxy + (dashpush + dashlength) * cd

        (x1, y1) = transform.inverse_xy_tup(tuple(c1))
        (x2, y2) = transform.inverse_xy_tup(tuple(c2))
        self.dashline.set_data((x1, x2), (y1, y2))

        # We now need to extend this vector out to
        # the center of the text area.
        # The basic problem here is that we're "rotating"
        # two separate objects but want it to appear as
        # if they're rotated together.
        # This is made non-trivial because of the
        # interaction between text rotation and alignment -
        # text alignment is based on the bbox after rotation.
        # We reset/force both alignments to 'center'
        # so we can do something relatively reasonable.
        # There's probably a better way to do this by
        # embedding all this in the object's transformations,
        # but I don't grok the transformation stuff
        # well enough yet.
        we = Text.get_window_extent(self, renderer=renderer)
        w, h = we.width(), we.height()
        # Watch for zeros
        if sin_theta == 0.0:
            dx = w
            dy = 0.0
        elif cos_theta == 0.0:
            dx = 0.0
            dy = h
        else:
            tan_theta = sin_theta / cos_theta
            dx = w
            dy = w * tan_theta
            if dy > h or dy < -h:
                dy = h
                dx = h / tan_theta
        cwd = array([dx, dy]) / 2
        cwd *= 1 + dashpad / sqrt(dot(cwd, cwd))
        cw = c2 + (dashdirection * 2 - 1) * cwd

        self._x, self._y = transform.inverse_xy_tup(tuple(cw))

        # Now set the window extent
        # I'm not at all sure this is the right way to do this.
        we = Text.get_window_extent(self, renderer=renderer)
        self._twd_window_extent = we.deepcopy()
        self._twd_window_extent.update(((c1[0], c1[1]), ), False)

        # Finally, make text align center
        Text.set_horizontalalignment(self, 'center')
        Text.set_verticalalignment(self, 'center')
Ejemplo n.º 9
0
    def update_coords(self, renderer):
        """Computes the actual x,y coordinates for
        self._mytext based on the input x,y and the
        dashlength. Since the rotation is with respect
        to the actual canvas's coordinates we need to
        map back and forth.
        """
        (x, y) = self.get_position()
        dashlength = self.get_dashlength()

        # Shortcircuit this process if we don't have a dash
        if dashlength == 0.0:
            self._mytext.set_position((x, y))
            return

        dashrotation = self.get_dashrotation()
        dashdirection = self.get_dashdirection()
        dashpad = self.get_dashpad()
        dashpush = self.get_dashpush()
        transform = self.get_transform()

        angle = get_rotation(dashrotation)
        theta = pi*(angle/180.0+dashdirection-1)
        cos_theta, sin_theta = cos(theta), sin(theta)

        # Compute the dash end points
        # The 'c' prefix is for canvas coordinates
        cxy = array(transform.xy_tup((x, y)))
        cd = array([cos_theta, sin_theta])
        c1 = cxy+dashpush*cd
        c2 = cxy+(dashpush+dashlength)*cd
        (x1, y1) = transform.inverse_xy_tup(tuple(c1))
        (x2, y2) = transform.inverse_xy_tup(tuple(c2))
        self.dashline.set_data((x1, x2), (y1, y2))

        # We now need to extend this vector out to
        # the center of the text area.
        # The basic problem here is that we're "rotating"
        # two separate objects but want it to appear as
        # if they're rotated together.
        # This is made non-trivial because of the
        # interaction between text rotation and alignment -
        # text alignment is based on the bbox after rotation.
        # We reset/force both alignments to 'center'
        # so we can do something relatively reasonable.
        # There's probably a better way to do this by
        # embedding all this in the object's transformations,
        # but I don't grok the transformation stuff
        # well enough yet.
        we = self._mytext.get_window_extent(renderer=renderer)
        w, h = we.width(), we.height()
        # Watch for zeros
        if sin_theta == 0.0:
            dx = w
            dy = 0.0
        elif cos_theta == 0.0:
            dx = 0.0
            dy = h
        else:
            tan_theta = sin_theta/cos_theta
            dx = w
            dy = w*tan_theta
            if dy > h or dy < -h:
                dy = h
                dx = h/tan_theta
        cwd = array([dx, dy])/2
        cwd *= 1+dashpad/sqrt(dot(cwd,cwd))
        cw = c2+(dashdirection*2-1)*cwd
        self._mytext.set_position(transform.inverse_xy_tup(tuple(cw)))

        # Now set the window extent
        # I'm not at all sure this is the right way to do this.
        we = self._mytext.get_window_extent(renderer=renderer)
        self._window_extent = we.deepcopy()
        self._window_extent.update(((c1[0], c1[1]),), False)

        # Finally, make text align center
        self._mytext.set_horizontalalignment('center')
        self._mytext.set_verticalalignment('center')
Ejemplo n.º 10
0
def _norm(x):
    "return sqrt(x dot x)"
    return numerix.mlab.sqrt(dot(x, x))
Ejemplo n.º 11
0
def dist(x, y):
    'return the distance between two points'
    d = x - y
    return numerix.mlab.sqrt(dot(d, d))