Checking if clicks are within a graphic object [Py

2019-06-01 16:01发布

问题:

Here is the module I'm using: http://mcsp.wartburg.edu/zelle/python/graphics/graphics.pdf

I want to see whether a user's clicks are within a shape or not. I used the in operator, but I know that is incorrect. Below is a chunk of my code:

win = GraphWin("Click Speed", 700, 700)

theTarget = drawTarget(win, random.randrange(0,685), random.randrange(0,685))

while theTarget in win:
    click = win.getMouse()
    if click in theTarget:
        print("Good job")

I left out the code that draws theTarget shape because it is length and unnecessary. It is a moving circle.

I'm using a while loop so it allows me to constantly get the user's clicks.

How do I go about checking whether or not a user's clicks are in the specified Target shape by using the getMouse() command?

I'm going to have to use this in the future for more abstract shapes (not simple circles).

回答1:

Circle

For the simple case of a circle, you can determine whether the mouse is inside using the distance formula. For example:

# checks whether pt1 is in circ
def inCircle(pt1, circ):

    # get the distance between pt1 and circ using the
    # distance formula
    dx = pt1.getX() - circ.getCenter().getX()
    dy = pt1.getY() - circ.getCenter().getY()
    dist = math.sqrt(dx*dx + dy*dy)

    # check whether the distance is less than the radius
    return dist <= circ.getRadius()

def main():
    win = GraphWin("Click Speed", 700, 700)

    # create a simple circle
    circ = Circle(Point(350,350),50)
    circ.setFill("red")
    circ.draw(win)

    while True:
        mouse = win.getMouse()
        if inCircle(mouse,circ):
            print ("Good job")

main()

Oval

For the more advanced example of an ellipse we will need to use a formula found here. Here is the function implemting that:

def inOval(pt1, oval):

    # get the radii
    rx = abs(oval.getP1().getX() - oval.getP2().getX())/2
    ry = abs(oval.getP1().getY() - oval.getP2().getY())/2

    # get the center
    h = oval.getCenter().getX()
    k = oval.getCenter().getY()

    # get the point
    x = pt1.getX()
    y = pt1.getY()

    # use the formula
    return (x-h)**2/rx**2 + (y-k)**2/ry**2 <= 1

Polygon

For a polygon of abitrary shape we need to reference this. I have converted that to a python equivalent for you. Check the link to see why it works because I am honestly not sure

def inPoly(pt1, poly):

    points = poly.getPoints()
    nvert = len(points) #the number of vertices in the polygon

    #get x and y of pt1
    x = pt1.getX()
    y = pt1.getY()

    # I don't know why this works
    # See the link I provided for details
    result = False
    for i in range(nvert):

        # note: points[-1] will give you the last element
        # convenient!
        j = i - 1

        #get x and y of vertex at index i
        vix = points[i].getX()
        viy = points[i].getY()

        #get x and y of vertex at index j
        vjx = points[j].getX()
        vjy = points[j].getY()

        if (viy > y) != (vjy > y) and (x < (vjx - vix) * (y - viy) / (vjy - viy) + vix):
            result = not result

    return result