Exemplo n.º 1
0
    def CalcScale(self, points, h, v, hittest=False):
        """Returns the proportion by which the xform needs to be scaled to make
        the hypot pass through the point.
        If hittest is set to true, this func doubles as a hittest, and checks
        if the point is inside the line's hitbox."""

        xf = Xform(points=points)
        a,d,b,e,c,f = xf.coefs

        # Get angle of the hypothenuse
        angle = polar(((b-a), (e-d)))[1]

        # create a rotated triangle and (c,f)->(h,v) vector. This way, the
        # hypothenuse is guaranteed to be horizontal, which makes everything
        # easier.
        xf.rotate(-angle)
        l, theta = polar(((h-c), (v-f)))
        width,height = rect((l, theta - angle))

        # return the result.
        # Note that xf.d and xf.e are guaranteed to be equal.
        if hittest:
            return xf.a < width < xf.b and \
                   abs(height - xf.d) < self.circle_radius
        return height / xf.d
Exemplo n.º 2
0
    def VertexHitTest(self, x, y):
        a,d,b,e,c,f = self.coefs

        if polar((x - c, y - f))[0] < self.parent.circle_radius:
            return 'o'
        elif polar((x - a - c, y - d - f))[0] < self.parent.circle_radius:
            return 'x'
        elif polar((x - b - c, y - e - f))[0] < self.parent.circle_radius:
            return 'y'
Exemplo n.º 3
0
    def VertexHitTest(self, mousepos):
        """Checks if the given point is on top of a vertex."""
        for xform in self.IterXforms():
            x, y, o = xform.points

            if polar(mousepos - o)[0] < self.circle_radius:
                cb = (partial(setattr, xform, "pos")
                      if config["Lock-Axes"] else partial(setattr, xform, "o"))
                return o, xform, cb
            elif polar(mousepos - x)[0] < self.circle_radius:
                return x, xform, partial(setattr, xform, "x")
            elif polar(mousepos - y)[0] < self.circle_radius:
                return y, xform, partial(setattr, xform, "y")

        return None, None, None
Exemplo n.º 4
0
    def VertexHitTest(self,x,y):
        """Checks if the given point is on top of a vertex."""

        for xform in self.IterXforms():
            xf = xform if not config['Edit-Post-Xform'] else xform.post
            a,d,b,e,c,f = xf.coefs

            if polar((x - c, y - f))[0] < self.circle_radius:
                return (xform, partial(setattr, xf, "pos") if config["Lock-Axes"] else partial(setattr, xf, "o"))
            elif polar((x - a - c, y - d - f))[0] < self.circle_radius:
                return xform, partial(setattr, xf, "x")
            elif polar((x - b - c, y - e - f))[0] < self.circle_radius:
                return xform, partial(setattr, xf, "y")

        return None, None
Exemplo n.º 5
0
    def VertexHitTest(self,x,y):
        """Checks if the given point is on top of a vertex."""
        for xform in self.IterXforms():
            a,d,b,e,c,f = xform.coefs

            if polar((x - c, y - f))[0] < self.circle_radius:
                cb = (partial(setattr, xform, "pos") if config["Lock-Axes"] 
                      else partial(setattr, xform, "o"))
                return xform.o, xform, cb
            elif polar((x - a - c, y - d - f))[0] < self.circle_radius:
                return xform.x, xform, partial(setattr, xform, "x")
            elif polar((x - b - c, y - e - f))[0] < self.circle_radius:
                return xform.y, xform, partial(setattr, xform, "y")

        return None, None, None
Exemplo n.º 6
0
    def SideHitTest(self, mousepos):
        """Checks if the given point is near one of the triangle sides
        or corners."""
        for xform in self.IterXforms():
            xf = xform  # TODO:refactor
            x, y, o = xf.points
            for points, func in (((x, y, o), 'scale'), ((x, o, y), 'rotate_x'),
                                 ((y, o, x), 'rotate_y')):
                if self.CalcScale(points, mousepos, hittest=True):
                    return (points[:2], xform,
                            self.side_helper(xf, func, mousepos))

        # TODO: detect the actual lines. Right now, it just checks a radius
        # from the middle point.
        radius = self.circle_radius * 3  # better too big than too small.
        for i, j, k in (self._cornerpoints):
            if polar(mousepos - j)[0] < radius:
                if config["Edit-Post-Xform"]:
                    xform = self.parent.ActiveXform.post
                else:
                    xform = self.parent.ActiveXform
                return (i, j,
                        k), xform, self.side_helper(xform, 'rotate', mousepos)

        return None, None, None
Exemplo n.º 7
0
    def side_helper(self, xform, funcname, mousepos):
        """Takes the result of SideHitTest and builds a proper callback."""
        if funcname == 'scale':

            def cb(pos):
                return xform.scale(self.CalcScale(xform.points, pos))

            return cb

        if funcname == "rotate":
            pivot = xform.o
            func = partial(xform.rotate, pivot=pivot)
        elif config["Lock-Axes"]:
            pivot = (0, 0) if config["World-Pivot"] else xform.o
            func = partial(xform.rotate, pivot=pivot)
        else:
            pivot = xform.o
            func = getattr(xform, funcname)

        def cb(pos):
            angle = polar(pos - pivot)[1]
            func(angle - cb.prev_angle)
            cb.prev_angle = angle

        cb.prev_angle = polar(mousepos - pivot)[1]
        return cb
Exemplo n.º 8
0
    def SideHitTest(self, h, v):
        """Checks if the given point is near one of the triangle sides
        or corners."""
        for xform in self.IterXforms():
            xf = xform # TODO:refactor
            x,y,o = xf.points
            for points,func in (((x,y,o), 'scale'),
                                ((x,o,y), 'rotate_x'),
                                ((y,o,x), 'rotate_y')):
                if self.CalcScale(points, h, v, hittest=True):
                    return (points[:2], xform,
                            self.side_helper(xf, func, h,v))

        # TODO: detect the actual lines. Right now, it just checks a radius
        # from the middle point.
        radius = self.circle_radius * 3 # better too big than too small.
        for i,j,k in (self._cornerpoints):
            if polar((h - j[0], v - j[1]))[0] < radius:
                if config["Edit-Post-Xform"]:
                    xform = self.parent.ActiveXform.post
                else:
                    xform = self.parent.ActiveXform
                return ((i,j,k), xform, self.side_helper(xform, 'rotate', h,v))

        return None, None, None
Exemplo n.º 9
0
    def CalcScale(self, points, mousepos, hittest=False):
        """Returns the proportion by which the xform needs to be scaled to make
        the hypot pass through the point.
        If hittest is set to true, this func doubles as a hittest, and checks
        if the point is inside the line's hitbox."""
        x, y, o = points

        # The idea is simple. Recenter the system around x, and rotate it so
        # the side under test runs along the x-axis.
        l, theta = polar(y - x)
        angle = N.array((0, theta))
        width, height = rect(polar(mousepos - x) - angle)

        # return the result.
        if hittest:
            return 0 < width < l and abs(height) < self.circle_radius
        else:
            ref_height = rect(polar(o - x) - angle)[1]
            return (ref_height - height) / ref_height
Exemplo n.º 10
0
def angle_helper(*points):
    """Given 3 vectors with the same origin, checks if the first falls
    between the other 2."""
    itr = (polar(i)[1] for i in points)
    vect = itr.next()  # vector being checked
    low, high = sorted(itr)  # the 2 triangle legs.
    if high - low > 180:
        low, high = high - 360, low
    if vect > high:
        vect -= 360
    return high > vect > low
Exemplo n.º 11
0
def angle_helper(*points):
    """Given 3 vectors with the same origin, checks if the first falls
    between the other 2."""
    itr = (polar(i)[1] for i in points)
    vect = itr.next() # vector being checked
    low, high = sorted(itr) # the 2 triangle legs.
    if high - low > 180:
        low, high = high-360, low
    if vect > high:
        vect -= 360
    return high > vect > low
Exemplo n.º 12
0
    def side_helper(self, xform, funcname, h, v):
        """Takes the result of SideHitTest and builds a proper callback."""
        if funcname == 'scale':
            def cb((h,v)):
                return xform.scale(self.CalcScale(xform.points, h, v))
            return cb

        if funcname == "rotate" or config["Lock-Axes"]:
            pivot = (0,0) if config["World-Pivot"] else xform.o
            func = partial(xform.rotate, pivot=pivot)
        else:
            pivot = xform.o
            func = getattr(xform, funcname)

        def cb((h, v)):
            angle = polar((h - pivot[0], v - pivot[1]))[1]
            func(angle - cb.prev_angle)
            cb.prev_angle = angle
        cb.prev_angle = polar((h - pivot[0], v - pivot[1]))[1]
        return cb
Exemplo n.º 13
0
 def cb(pos):
     angle = polar(pos - pivot)[1]
     func(angle - cb.prev_angle)
     cb.prev_angle = angle
Exemplo n.º 14
0
 def cb((h, v)):
     angle = polar((h - pivot[0], v - pivot[1]))[1]
     func(angle - cb.prev_angle)
     cb.prev_angle = angle