【问题标题】:Calculating the bounding box of a random triangle using coordinates使用坐标计算随机三角形的边界框
【发布时间】:2013-03-12 18:20:17
【问题描述】:

我正在寻找一种合适的方法来计算三角形的矩形边界框,该三角形具有三个角作为点 - (x1,y1)、(x2,y2)、(x3,y3)。

这是我正在使用的数据类型(按照建议,我添加了更多构造函数):

data Shape =
     Circle Point Double |
     Rectangle Point Point |
     Triangle Point Point Point

边界框函数的格式应该是“bounding :: Shape -> Shape”。 我也试过矩形和圆形的边界框:

bounding :: Shape -> Shape
bounding (Rectangle (Point x y) (Point z z1)) = (Rectangle (Point x y) (Point z z1))
bounding (Circle (Point p w) r) = (Rectangle (Point (p-r) (w-r)) (Point (p+r) (w+r)))

如果应该使用图形坐标系,这些是否正确(其中 (x,y) 坐标应该被视为 (x,-y))?

有人可以帮帮我吗? 附言不需要图形库。

【问题讨论】:

  • 你的输出类型肯定应该是某种边界框而不是另一个三角形?
  • @dave4420 是的,输出应该只是一个包围矩形。
  • 但是Shape 的类型仅将三角形列为可能的形状。你遗漏了什么吗?

标签: haskell geometry bounding-box


【解决方案1】:

你试过什么?你有代码吗?

你需要:

 data Shape = Triangle Point Point Point | Rectangle Point Point

假设 x 向右增加,y 向上增加。左上角将是 (min{x1, x2, x3}, max{y1, y2, y3}),你需要右下角。


编辑

x 应该向右增加,y 向下增加。我添加了三角形一,删除了不必要的括号并派生(显示)以便能够打印形状数据类型。完整代码:

data Point = Point Double Double deriving (Show)

data Shape =
        Circle Point Double |
        Rectangle Point Point |
        Triangle Point Point Point deriving (Show)

bounding :: Shape -> Shape
bounding (Rectangle (Point x y) (Point z z1)) = Rectangle (Point x y) (Point z z1)
bounding (Circle (Point p w) r) = Rectangle (Point (p-r) (w-r)) (Point (p+r) (w+r))
bounding (Triangle (Point x1 y1) (Point x2 y2) (Point x3 y3)) = Rectangle 
        (Point (minimum [x1, x2, x3]) (minimum [y1, y2, y3])) 
        (Point (maximum [x1, x2, x3]) (maximum [y1, y2, y3]))

【讨论】:

  • Tyvm 为您解答。实际上,y 应该向下增加...(图形坐标要求)
  • 最好的问候,凯蒂卡!非常感谢您的支持!
【解决方案2】:

根据 @dave4420 的出色观察,我假设 Rectangles 与 x/y 轴对齐。

根据您对Circle 的规则,在Rectangle 中,x,y 最小的点排在第一位,x,y 最大的点排在第二位。

您可能应该坚持使用带有数字后缀的x 和y,而不是发明像p、w、z 和z1 这样非常令人困惑的新名称。

Rectangle 的边界框是 Rectangle 本身。

Triangle 的边界框将是一个Rectangle,从任意点来看,x,y 的最小和最大。

bounding :: Shape -> Shape
bounding rect@(Rectangle _ _) = rect
bounding (Circle (Point x y) r) = Rectangle p1 p2 where
  p1 = (Point (x-r) (y-r))
  p2 = (Point (x+r) (y+r))
bounding (Triangle (Point x1 y1) (Point x2 y2) (Point x3 y3)) = Rectangle p1 p2 where
  p1 = Point (minimum [x1 x2 x3]) (minimum [y1 y2 y3])
  p2 = Point (maximum [x1 x2 x3]) (maximum [y1 y2 y3])

【讨论】:

    【解决方案3】:

    我发布这个答案只是为了说明边界框和矩形不是一回事。

    data Point = Point Double Double   -- Point x y
    
    data BoundingBox = BoundingBox Double Double Double Double
                                -- top    left   bottom right
    
    data Shape
        = Circle Point Double
        | Rectangle Point Point Double
            -- yes, you need two points and a scalar to specify arbitrary rectangles
        | Triangle Point Point Point
    
    boundingBox :: Shape -> BoundingBox
    boundingBox (Circle (Point x y) r) = BoundingBox (y-r) (x-r) (y+r) (x+r)
    boundingBox (Rectangle (Point x0 y0) (Point x1 y1) d)
            = BoundingBox (minimum ys) (minimum xs) (maximum ys) (maximum xs) where
        xs = [x0, x1, x1+dx, x0+dx]
        ys = [y0, y1, y1+dy, y0+dy]
        d' = d / ((x0-x1)^^2 + ((y0-y1)^^2)
        dx = d' * (y0-y1)
        dy = d' * (x1-x0)
    boundingBox (Triangle (Point x0 y0) (Point x1 y1) (Point x2 y2))
            = BoundingBox (minimum ys) (minimum xs) (maximum ys) (maximum xs) where
        xs = [x0, x1, x2]
        ys = [y0, y1, y2]
    

    作为练习,从Rectangle 和Triangle 案例中提取公共代码。 (查找和修复我在Rectangle 案例中放置的任何错误的奖励积分。)

    【讨论】:

    • 我认为您的Rectangle 不需要与轴对齐。但是,通过三个点,您可以指定没有 90 度角的事物。你只需要两个点和一个标量。点指定一侧的长度和角度,标量指定另一垂直边的长度。
    猜你喜欢
    • 2013-09-10
    • 2017-02-19
    • 2010-10-11
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 2014-04-23
    • 2021-02-20
    • 1970-01-01
    相关资源
    最近更新 更多