这是一个与语言无关的问题。给定l,t,w,h
(左,顶,宽,高)和点x,y
的矩形尺寸,如何找到矩形周长上最近的点?
我试图在Lua中解决它,但任何其他语言都可以。到目前为止,这是我的最大努力:
local function nearest(x, a, b)
if a <= x and x <= b then
return x
elseif math.abs(a - x) < math.abs(b - x) then
return a
else
return b
end
end
local function getNearestPointInPerimeter(l,t,w,h, x,y)
return nearest(x, l, l+w), nearest(y, t, t+h)
end
这适用于周边外点或周边本身。但是对于外围的内部,它会失败(它只会返回x,y
)
我的直觉告诉我解决方案应该很简单,但我似乎找不到它。
答案 0 :(得分:14)
这次我试图抓住点到矩形任何一侧的最小距离。
local abs, min, max = math.abs, math.min, math.max
local function clamp(x, lower, upper)
return max(lower, min(upper, x))
end
local function getNearestPointInPerimeter(l,t,w,h, x,y)
local r, b = l+w, t+h
x, y = clamp(x, l, r), clamp(y, t, b)
local dl, dr, dt, db = abs(x-l), abs(x-r), abs(y-t), abs(y-b)
local m = min(dl, dr, dt, db)
if m == dt then return x, t end
if m == db then return x, b end
if m == dl then return l, y end
return r, y
end
答案 1 :(得分:1)
设C1,C2,C3,C4为矩形的顶点。
从给定的A点开始绘制2条为
的线
垂直于矩形的边。设B1,B2,B3,B4
是与他们确定的线的交叉点
矩形的两边(其中一些Bk也可能重合
例如如果A = Ck某些k)。你的解决方案是Bk
的要点之一
或其中一个点Ck,只需蛮力检查8点
(同样,这8个点中的一些可能重合,但这无关紧要。)
答案 2 :(得分:1)
另一种可能的算法(类似于我的第一个答案)可以在这里找到 - 来自Dinre。
Calculating the distance between polygon and point in R
看起来很简单,实际上它是我的第一个答案的简化(可能更好)版本。
找到给定点A的两个最近的矩形顶点Ci和Cj。
找到从A到线(Ci,Cj)的垂线与线(Ci,Cj)相交的点M.
您的解决方案是Ci或Cj或M.
对我而言似乎适用于所有情况(无论A点位于飞机的哪个位置)。
答案 3 :(得分:0)
local function getNearestPointInPerimeter(l,t,w,h, x,y)
-- x axis increases to the right
-- y axis increases down
local r = l + w
local b = t + h
local inside = true -- unless later proven otherwise
-- if the point (x,y) is outside the rectangle,
-- push it once to the nearest point on the perimeter, or
-- push it twice to the nearest corner.
if x < l then x = l; inside = false; end
if x > r then x = r; inside = false; end
if y < t then y = t; inside = false; end
if y > b then y = b; inside = false; end
-- if the point (x,y) is inside the rectangle,
-- push it once to the closest side.
if inside then
local dt = math.abs (y - t)
local db = math.abs (y - b)
local dl = math.abs (x - l)
local dr = math.abs (x - r)
if dt <= db and dt <= dl and dt <= dr then
y = t
elseif db <= dl and db <= dr then
y = b
elseif dl <= dr then
x = l
else
x = r
end
end
return x,y
end
答案 4 :(得分:0)
感谢您提出问题和答案!这是我选择的答案的python翻译版本,以防任何人需要它。唯一的自定义部分是使用lambda的钳位内联函数定义。
我在使用Qt的QRect和QPoint的GUI中成功地使用了它,以确保在QGraphcsView中显示出某些内容。
<?xml version="1.0" encoding="utf-8"?>
<CheckBox
android:id="@+id/cb_row_item"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="Category name goes here"
android:textSize="15sp"/>