查找使其覆盖 2D 中最大点的矩形位置 space
Finding rectangle position that makes it cover maximum points in 2D space
给定一个带有 X 点的 2D Space,我如何才能有效地找到放置固定大小矩形的位置,以便它覆盖尽可能多的 X 点?
我需要按照这些思路在我正在构建的 2D 游戏中定位视口。
- 从左到右对点进行排序。在最左边的点设置一个
left
指针,在落在 left + width
范围内的最右边的点设置一个 right
指针。然后遍历所有的点,每次都重新计算right
指针的位置,直到到最后一个点。
- 从上到下对左右之间的每个点子集进行排序。在最高点设置一个
top
指针,在top + height
范围内的最低点设置一个bottom
指针。然后遍历所有的点,每次都重新计算bottom
指针的位置,直到到最后一个点。
- 对于左、右、上、下之间的每个点子集,检查它有多少点,并存储最佳子集。
- 找到最佳子集后,矩形的中心位于最左边和最右边的点的中间,以及最高点和最低点的中间。
下面是Javascript中的一个简单实现,可以在很多地方进行优化。 运行 用于查看随机数据结果的代码片段。
function placeRectangle(p, width, height) {
var optimal, max = 0;
var points = p.slice();
points.sort(horizontal);
for (var left = 0, right = 0; left < points.length; left++) {
while (right < points.length && points[right].x <= points[left].x + width) ++right;
var column = points.slice(left, right);
column.sort(vertical);
for (var top = 0, bottom = 0; top < column.length; top++) {
while (bottom < column.length && column[bottom].y <= column[top].y + height) ++bottom;
if (bottom - top > max) {
max = bottom - top;
optimal = column.slice(top, bottom);
}
if (bottom == column.length) break;
}
if (right == points.length) break;
}
var left = undefined, right = undefined, top = optimal[0].y, bottom = optimal[optimal.length - 1].y;
for (var i = 0; i < optimal.length; i++) {
var x = optimal[i].x;
if (left == undefined || x < left) left = x;
if (right == undefined || x > right) right = x;
}
return {x: (left + right) / 2, y: (top + bottom) / 2};
function horizontal(a, b) {
return a.x - b.x;
}
function vertical(a, b) {
return a.y - b.y;
}
}
var width = 160, height = 90, points = [];
for (var i = 0; i < 10; i++) points[i] = {x: Math.round(Math.random() * 300), y: Math.round(Math.random() * 200)};
var rectangle = placeRectangle(points, width, height);
// SHOW RESULT IN CANVAS
var canvas = document.getElementById("canvas");
canvas.width = 300; canvas.height = 200;
canvas = canvas.getContext("2d");
paintRectangle(canvas, rectangle.x - width / 2, rectangle.y - height / 2, width, height, 1, "red");
for (var i in points) paintDot(canvas, points[i].x, points[i].y, 2, "blue");
function paintDot(canvas, x, y, size, color) {
canvas.beginPath();
canvas.arc(x, y, size, 0, 6.2831853);
canvas.closePath();
canvas.fillStyle = color;
canvas.fill();
}
function paintRectangle(canvas, x, y, width, height, line, color) {
canvas.beginPath();
canvas.rect(x, y, width, height);
canvas.closePath();
canvas.lineWidth = line;
canvas.strokeStyle = color;
canvas.stroke();
}
<BODY STYLE="margin: 0; border: 0; padding: 0;">
<CANVAS ID="canvas" STYLE="width: 300px; height: 200px; float: left; background-color: #F8F8F8;"></CANVAS>
</BODY>
如果有人正在寻找@m69 的 C++ 代码,那么这里是:
struct str {
bool operator() (cv::Point2f a, cv::Point2f b)
{
return a.x < b.x;
}
} compX;
struct str1 {
bool operator() (cv::Point2f a, cv::Point2f b)
{
return a.y < b.y;
}
} compY;
cv::Point2f placeRectangle(std::vector<cv::Point2f> p, float width, float height)
{
double max = 0;
std::vector<cv::Point2f> points = p;
std::sort(points.begin(), points.end(), compX);
std::vector<cv::Point2f> optimal;
float left = 0.0;
float right = 0.0;
for (left = 0, right = 0; left < points.size(); ++left)
{
while (right < points.size() && points[right].x <= points[left].x + width) ++right;
std::vector<cv::Point2f> myVector1(points.begin() + left, points.begin() + right);
std::vector<cv::Point2f> column = myVector1;
std::sort(column.begin(), column.end(), compY);
for (int top = 0, bottom = 0; top < column.size(); top++)
{
while (bottom < column.size() && column[bottom].y <= column[top].y + height) ++bottom;
if (bottom - top > max)
{
max = bottom - top;
std::vector<cv::Point2f> myVector(column.begin() + top, column.begin() + bottom);
optimal = myVector;
}
if (bottom == column.size()) break;
}
if (right == points.size()) break;
}
left = 0; right = 0; float top = optimal[0].y; float bottom = optimal[optimal.size() - 1].y;
for (int i = 0; i < optimal.size(); i++)
{
float x = optimal[i].x;
if (left == 0 || x < left) left = x;
if (right == 0 || x > right) right = x;
}
return cv::Point2f((left + right) / 2.0, (top + bottom) / 2.0);
}
给定一个带有 X 点的 2D Space,我如何才能有效地找到放置固定大小矩形的位置,以便它覆盖尽可能多的 X 点?
我需要按照这些思路在我正在构建的 2D 游戏中定位视口。
- 从左到右对点进行排序。在最左边的点设置一个
left
指针,在落在left + width
范围内的最右边的点设置一个right
指针。然后遍历所有的点,每次都重新计算right
指针的位置,直到到最后一个点。 - 从上到下对左右之间的每个点子集进行排序。在最高点设置一个
top
指针,在top + height
范围内的最低点设置一个bottom
指针。然后遍历所有的点,每次都重新计算bottom
指针的位置,直到到最后一个点。 - 对于左、右、上、下之间的每个点子集,检查它有多少点,并存储最佳子集。
- 找到最佳子集后,矩形的中心位于最左边和最右边的点的中间,以及最高点和最低点的中间。
下面是Javascript中的一个简单实现,可以在很多地方进行优化。 运行 用于查看随机数据结果的代码片段。
function placeRectangle(p, width, height) {
var optimal, max = 0;
var points = p.slice();
points.sort(horizontal);
for (var left = 0, right = 0; left < points.length; left++) {
while (right < points.length && points[right].x <= points[left].x + width) ++right;
var column = points.slice(left, right);
column.sort(vertical);
for (var top = 0, bottom = 0; top < column.length; top++) {
while (bottom < column.length && column[bottom].y <= column[top].y + height) ++bottom;
if (bottom - top > max) {
max = bottom - top;
optimal = column.slice(top, bottom);
}
if (bottom == column.length) break;
}
if (right == points.length) break;
}
var left = undefined, right = undefined, top = optimal[0].y, bottom = optimal[optimal.length - 1].y;
for (var i = 0; i < optimal.length; i++) {
var x = optimal[i].x;
if (left == undefined || x < left) left = x;
if (right == undefined || x > right) right = x;
}
return {x: (left + right) / 2, y: (top + bottom) / 2};
function horizontal(a, b) {
return a.x - b.x;
}
function vertical(a, b) {
return a.y - b.y;
}
}
var width = 160, height = 90, points = [];
for (var i = 0; i < 10; i++) points[i] = {x: Math.round(Math.random() * 300), y: Math.round(Math.random() * 200)};
var rectangle = placeRectangle(points, width, height);
// SHOW RESULT IN CANVAS
var canvas = document.getElementById("canvas");
canvas.width = 300; canvas.height = 200;
canvas = canvas.getContext("2d");
paintRectangle(canvas, rectangle.x - width / 2, rectangle.y - height / 2, width, height, 1, "red");
for (var i in points) paintDot(canvas, points[i].x, points[i].y, 2, "blue");
function paintDot(canvas, x, y, size, color) {
canvas.beginPath();
canvas.arc(x, y, size, 0, 6.2831853);
canvas.closePath();
canvas.fillStyle = color;
canvas.fill();
}
function paintRectangle(canvas, x, y, width, height, line, color) {
canvas.beginPath();
canvas.rect(x, y, width, height);
canvas.closePath();
canvas.lineWidth = line;
canvas.strokeStyle = color;
canvas.stroke();
}
<BODY STYLE="margin: 0; border: 0; padding: 0;">
<CANVAS ID="canvas" STYLE="width: 300px; height: 200px; float: left; background-color: #F8F8F8;"></CANVAS>
</BODY>
如果有人正在寻找@m69 的 C++ 代码,那么这里是:
struct str {
bool operator() (cv::Point2f a, cv::Point2f b)
{
return a.x < b.x;
}
} compX;
struct str1 {
bool operator() (cv::Point2f a, cv::Point2f b)
{
return a.y < b.y;
}
} compY;
cv::Point2f placeRectangle(std::vector<cv::Point2f> p, float width, float height)
{
double max = 0;
std::vector<cv::Point2f> points = p;
std::sort(points.begin(), points.end(), compX);
std::vector<cv::Point2f> optimal;
float left = 0.0;
float right = 0.0;
for (left = 0, right = 0; left < points.size(); ++left)
{
while (right < points.size() && points[right].x <= points[left].x + width) ++right;
std::vector<cv::Point2f> myVector1(points.begin() + left, points.begin() + right);
std::vector<cv::Point2f> column = myVector1;
std::sort(column.begin(), column.end(), compY);
for (int top = 0, bottom = 0; top < column.size(); top++)
{
while (bottom < column.size() && column[bottom].y <= column[top].y + height) ++bottom;
if (bottom - top > max)
{
max = bottom - top;
std::vector<cv::Point2f> myVector(column.begin() + top, column.begin() + bottom);
optimal = myVector;
}
if (bottom == column.size()) break;
}
if (right == points.size()) break;
}
left = 0; right = 0; float top = optimal[0].y; float bottom = optimal[optimal.size() - 1].y;
for (int i = 0; i < optimal.size(); i++)
{
float x = optimal[i].x;
if (left == 0 || x < left) left = x;
if (right == 0 || x > right) right = x;
}
return cv::Point2f((left + right) / 2.0, (top + bottom) / 2.0);
}