【问题标题】:Verifying Mouse Position Within Triangle - Python验证三角形内的鼠标位置 - Python
【发布时间】:2015-11-12 08:45:03
【问题描述】:

**这是编程课程的一部分,我们被要求使用的模块通常不会在其他情况下使用。我会尽力解释我的代码(虽然它是不言自明的)

编辑:如果你很好奇,我必须使用Myro,而我用来获取鼠标点击坐标的代码是:mouseX, mouseY = win.getMouse() # "win" refers to a Window object

我正在创建“按钮”,当单击时执行某种形式的操作。我使用了三种不同的形状:矩形、圆形和三角形。

对于矩形:

# The numbers used in this example are the coordinates on an XY plane
# mouseX refers to the X coord of a recent mouse click; mouseY on the Y axis
if mouseX >= 70 and mouseX <= 120:
        if mouseY >= 10 and mouseY <= 35:
            print("rectangle button clicked")

对于圈子,我得到了this question的帮助,最后得到了这个代码:

# mouseX and mouseY, same as rectangle example
if sqrt((mouseX-660)**2 + (mouseY-270)**2) <= 30:
        print("circle button clicked")

我尝试使用的最后一个形状是三角形。我不确定如何确保mouseXmouseY 在形状的坐标范围内。我的数学相当糟糕,但我假设有一些公式可以使用(例如圆圈示例)。非常感谢。

【问题讨论】:

    标签: python graphics myro calico-project


    【解决方案1】:

    这样定义你的三角形和鼠标坐标:

    并定义两个向量uv2D叉积

    如果向量u 位于v右侧,则为正,如果位于左侧,则为负。

    所以您正在寻找的四个条件是:

    ...鼠标点击。

    (可以使用涉及点积的替代方法,但它涉及效率相当低的平方根)

    抱歉缺少代码 - 我讨厌 Python(是的,我说过)。但这应该提供实现它所需的数学运算。

    【讨论】:

    • 除了中间的等式U x V = UxVy - UyVx,我可以理解这里的所有内容。这些变量从何而来(分别是 U 和 V?)
    • 另外,感谢您对它背后的数学的非凡洞察力。我数学不是很好,但这很容易理解!
    • @Aaron 抱歉回复晚了 - U 和 V 只是两个任意二维向量,具有分量 (Ux, Uy) 和 (Vx, Vy)。将此公式应用于任意两个向量以获得它们的叉积。
    【解决方案2】:

    我在this 问题中找到了答案,用 C 语言编写(我相信)。我已将代码改写成 Python 并留给其他人使用。

    代码:

    def sign(p1, p2, p3): #all Points
        return (p1.getX() - p3.getX()) * (p2.getY() - p3.getY()) - (p2.getX() - p3.getX()) * (p1.getY() - p3.getY())
    
    def inTriangle(pt, v1, v2, v3): #all Points, pt = mouse, v = triangle vertex
        b1 = sign(pt, v1, v2) < 0.0
        b2 = sign(pt, v2, v3) < 0.0
        b3 = sign(pt, v3, v1) < 0.0
        return ((b1 == b2) and (b2 == b3))
    

    测试:

    mouseX, mouseY = win.getMouse() #Myro module, win = Window object
    a = Point(662,200)
    b = Point(1,1)
    print(inTriangle(a, Point(661,156), Point(633,217), Point(688,218))) #TRUE!
    print(inTriangle(b, Point(661,156), Point(633,217), Point(688,218))) #FALSE!
    triangle = [Point(661, 156), Point(633, 217), Point(688, 218)]
    if inTriangle(Point(mouseX, mouseY), triangle[0], triangle[1], triangle[2]):
        print("clicked up")
    

    【讨论】:

      【解决方案3】:

      使用叉积 - 必须全部为正或全部为负。

      def line_point_pos(start, end, point):
          """right: negative, left: positive, onedge: zero"""
          A = end[0]-start[0], end[1]-start[1]
          B = point[0]-start[0], point[1]-start[1]
          # return z-component of cross product
          return A[0]*B[1] - A[1]*B[0]
      
      def in_polygon(vertices, point, onedges=True):
          """find out if the point is inside the polygon"""
          edges = zip(vertices, vertices[1:] + [vertices[0]])
      
          zs = [line_point_pos(s, e, point) for s,e in edges]
          if 0 in zs:
              return onedges
          return all(z>0 for z in zs) or all(z<0 for z in zs)
      
      triangle = [(1, 1), (10, 1), (5, 10)]
      a = 5, 10
      print(in_polygon(triangle, a))      # True
      

      【讨论】:

      • 除非我不理解某些东西,否则您的代码总是返回 True。
      猜你喜欢
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-05
      • 2012-03-01
      相关资源
      最近更新 更多