Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 是否有一个简单的;“以矩形表示的点”;环绕图的算法?_Algorithm_Delphi_Math_Geometry_Coordinates - Fatal编程技术网

Algorithm 是否有一个简单的;“以矩形表示的点”;环绕图的算法?

Algorithm 是否有一个简单的;“以矩形表示的点”;环绕图的算法?,algorithm,delphi,math,geometry,coordinates,Algorithm,Delphi,Math,Geometry,Coordinates,我正试图建立一个矩形网格,可以在边缘环绕。任何玩电子游戏的人都可能熟悉这个概念:在世界地图上朝一个方向走足够远,你就会回到你开始的地方。但是,这会给设置视口带来一些困难,因为边可以滚动到负坐标区域 取负坐标并确定其实际值非常容易: function GetRealCoords(value: TPoint): TPoint; begin result := ModPoints(AddPoints(value, MAP_SIZE), MAP_SIZE); end; 其中,AddPoints和

我正试图建立一个矩形网格,可以在边缘环绕。任何玩电子游戏的人都可能熟悉这个概念:在世界地图上朝一个方向走足够远,你就会回到你开始的地方。但是,这会给设置视口带来一些困难,因为边可以滚动到负坐标区域

取负坐标并确定其实际值非常容易:

function GetRealCoords(value: TPoint): TPoint;
begin
   result := ModPoints(AddPoints(value, MAP_SIZE), MAP_SIZE);
end;
其中,AddPoints和ModPoints只需将
+
mod
运算符分别应用于两个输入的每个坐标,以产生输出值

问题是要逆转这一操作。给定一个点,其中两个坐标都是正的,一个树的顶部和左侧值可以是正的或负的(底部或右侧可以超出地图的边缘),并且地图大小在全局范围内声明,是否有任何方法可以确定该点是否位于观察矩形覆盖的区域内,而不必运行相同的计算多达四次?

我相信是这样

我能想到的最糟糕的情况(grid=[0,1)x[0,1])是: 顶部=-0.25,左侧=-0.25,底部=0.25,右侧=0.25

这看起来像(包装时):

现在,您必须测试四个角,以查看该点是否位于它们内部。 但是,我相信通过在空间[1,2)x[1,2]中执行测试,可以避免 问题,因为它再次变成一个矩形

 ______
|      |
|      |
|     _|_
|____|   |
     |___|
Width=Mod(Right-Left+MAP_SIZE,MAP_SIZE)
Height=Mod(Bottom-Top+MAP_SIZE,MAP_SIZE)
function PointInRect(aPoint:TPoint;aRect:TRect):boolean;
begin
  Result:=(aPoint.X >= aRect.Left  ) and 
          (aPoint.X <  aRect.Right ) and 
          (aPoint.Y >= aRect.Top   ) and 
          (aPoint.Y <  aRect.Bottom);
end;
通过计算矩形的宽度和高度来简化问题

 ______
|      |
|      |
|     _|_
|____|   |
     |___|
Width=Mod(Right-Left+MAP_SIZE,MAP_SIZE)
Height=Mod(Bottom-Top+MAP_SIZE,MAP_SIZE)
function PointInRect(aPoint:TPoint;aRect:TRect):boolean;
begin
  Result:=(aPoint.X >= aRect.Left  ) and 
          (aPoint.X <  aRect.Right ) and 
          (aPoint.Y >= aRect.Top   ) and 
          (aPoint.Y <  aRect.Bottom);
end;
现在,计算左上角的包裹位置

LeftNew=Mod(Left+MAP_SIZE,MAP_SIZE)
TopNew=Mod(Top+MAP_SIZE,MAP_SIZE)
计算新的底部和右侧:

RightNew=LeftNew+Width
BottomNew=TopNew+Height
现在,对于您希望测试的每个点,添加MAP_大小,并测试它是否位于新矩形内

TestNew=AddPoints(Test,MAP_SIZE)

If (TestNew.X>=LeftNew && TestNew.X<=RightNew && TestNew.Y>=TopNew && TestNew.T<=BottomNew)
{
  We have a point inside!
}
TestNew=AddPoints(测试,映射大小)

如果(TestNew.X>=LeftNew&&TestNew.X=TopNew&&TestNew.T,使用此选项可以测试点是否在矩形内

 ______
|      |
|      |
|     _|_
|____|   |
     |___|
Width=Mod(Right-Left+MAP_SIZE,MAP_SIZE)
Height=Mod(Bottom-Top+MAP_SIZE,MAP_SIZE)
function PointInRect(aPoint:TPoint;aRect:TRect):boolean;
begin
  Result:=(aPoint.X >= aRect.Left  ) and 
          (aPoint.X <  aRect.Right ) and 
          (aPoint.Y >= aRect.Top   ) and 
          (aPoint.Y <  aRect.Bottom);
end;
函数PointInRect(aPoint:TPoint;aRect:TRect):布尔;
开始
结果:=(aPoint.X>=aRect.Left)和
(aPoint.X=aRect.Top)和
(A点Y<正确的底部);
结束;
但如果我正确理解你的描述,你会想要这样的东西:

function NormalisePoint(aPoint:TPoint;aRect:TRect):TPoint;
var Width,Height:integer;
begin
  Width  := aRect.Right-aRect.Left;
  Height := aRect.Bottom-aRect.Top;

  if (Width=0) then
    aPoint.X := aRect.Left
  else
  begin
    while (aPoint.X< aRect.Left  ) do inc(aPoint.X,Width );
    while (aPoint.X>=aRect.Right ) do dec(aPoint.X,Width );
  end;

  if (Height=0) then
    aPoint.Y := aRect.Top
  else
  begin
    while (aPoint.Y< aRect.Top   ) do inc(aPoint.Y,Height);
    while (aPoint.Y>=aRect.Bottom) do dec(aPoint.Y,Height);
  end;
  Result := aPoint;
end;
函数NormalisePoint(aPoint:TPoint;aRect:TRect):TPoint;
变量宽度、高度:整数;
开始
宽度:=aRect.Right-aRect.Left;
高度:=aRect.Bottom-aRect.Top;
如果(宽度=0),则
aPoint.X:=左对齐
其他的
开始
而(aPoint.X=aRect.Right)do dec(aPoint.X,Width);
结束;
如果(高度=0),则
aPoint.Y:=aRect.Top
其他的
开始
while(aPoint.Y=aRect.Bottom)do dec(aPoint.Y,Height);
结束;
结果:=aPoint;
结束;

在进行二维操作之前,先考虑一维。你想知道一个数字是否在一个可能环绕的范围内,例如时钟上7到2的范围内是3。一旦这样,你就可以对X和Y坐标进行测试

我对更简单问题的解决方案:

//assumes start and end are both in [0, divisor). (Because .net and most other languages do modulus WRONG.)
double ClockDistance(double start, double end, double clockSize) {
    return (end - start + clockSize) % clockSize;
}
//assumes inclusive bounds
bool ClockBetween(int n, double start, double end, double clockSize) {
    return ClockDistance(start, n, clockSize) 
           <= ClockDistance(start, end, clockSize);
}
//假设开始和结束都在[0,除数中)。(因为.net和大多数其他语言都不正确。)
双时钟距离(双起点、双终点、双时钟尺寸){
返回(结束-开始+时钟大小)%clockSize;
}
//假设包含边界
布尔时钟间隔(整数n,双起点,双终点,双时钟大小){
返回时钟距离(开始,n,时钟大小)

哎哟!我很想在一般原则上否决这一点,只是因为我的“双倍增加”声明。这使它更难阅读。:(我不同意这种情况下的可读性论点,但我知道“with”Delphi开发人员的信条。我将以详细的方式重写它。作为补充,Delphi RTL已经有了一个函数来检查rect是否位于某个点:。