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
C# 确定不完整椭圆开口的代码_C#_Algorithm - Fatal编程技术网

C# 确定不完整椭圆开口的代码

C# 确定不完整椭圆开口的代码,c#,algorithm,C#,Algorithm,我有一个要渲染的截止椭圆。切割部分是通过与另一个椭圆相交来完成的(想象另一个椭圆挡住了原始椭圆) 参考下面的2个椭圆,其中t1,t2代表参数t1,t2,我画出椭圆,给出点p1,p2 如何使用数据结构捕获空的部分?我最初的伪代码是这样的: for(t = 0 to 360 degrees) { if(point_t intersects with ellipse) { if(P1 is not set) set t corresponding to P1 as s

我有一个要渲染的截止椭圆。切割部分是通过与另一个椭圆相交来完成的(想象另一个椭圆挡住了原始椭圆)

参考下面的2个椭圆,其中t1,t2代表参数t1,t2,我画出椭圆,给出点p1,p2

如何使用数据结构捕获空的部分?我最初的伪代码是这样的:

for(t = 0 to 360 degrees)
{
    if(point_t intersects with ellipse)
    {
        if(P1 is not set) set t corresponding to P1 as start_t;
        else set t corresponding to P2 as end_t
    }
}

然后,“截止”区域将由
start\t给出。您的图像暗示轴对齐的椭圆,如果不正确,请在OP中指定它

  • 两个椭圆的交点可以创建

    • 如果完全在内部/外部,则切断0
    • 1如果在单侧相交,则切断
    • 如果在两条边上相交,则为2条截止线
    • 完全截止是两个椭圆相同
  • 交点

    • 您需要获得所有交点
    • 所以要么用代数/数值方法求解它
    • x0+a0*cos(t0)=x1*a1*cos(t1)
    • y0+b0*sin(t0)=y1*b1*sin(t1)
    • 其中:
      x0,y0
      为中心,
      a0,b0
      为半轴,
      t0
      为第一个椭圆的参数
    • 其中:
      x1,y1
      为中心,
      a1,b1
      为半轴,
      t1
      为第二个椭圆的参数
    • 或者将问题转化为直线的交点
    • 以恒定角度扫掠布斯椭圆
    • 将每个椭圆变换为凸多边形
    • 点越多,得到的交点越精确
    • 如果两条线相互交叉,则选择其公共部分的中点
  • 存储什么信息

    • 在开始-结束形式中,需要间隙或其他间隙的参数对
    • 所以,对于每个交点,您需要确定它是间隙的起点还是终点
    • 因此,您应该有一个最多4个点/角度的交点参数列表(按角度排序)
  • 在某些情况下,您可以忽略0,1分

  • 2分是最简单的情况


    • 所以你有交角
      ang0,ang1
      其中
      ang0,因为两个椭圆可能相交4次(因此无论如何会产生两个截止区域),我建议你像你建议的那样运行代码,但将所有结果间隔存储在一个列表中

      意思是:

      if(点与椭圆相交)
      true
      的第一个值存储为第一个间隔的起始值。如果(点与椭圆相交)
      为false并将其设置为结束参数,则继续操作,直到
      。然后重复


      结果是一个开始/结束值列表,您可以对其进行迭代以进行进一步计算。此外,如果您需要每个间隔的长度,您可以在间隔以0开始时修改列表,以将例如
      {340,20}
      存储为交叉点间隔

      假设您只需要描述一个截止时间间隔,我建议使用(Begin,Extent)表示法,而不是(Begin,End)。“范围”参数是一个范围为0°到360°的值,它对角度的跳跃不敏感。您甚至可以为其指定一个符号,以便区分顺时针和逆时针的遍历


      如果您想描述一系列圆弧,也可以使用类似的技巧:您可以为每个圆弧提供(开始,范围)信息,或者为交替包含/排除的圆弧提供(开始,范围,范围…)边界。

      冒着看起来很傻的风险,我是否可以建议检查椭圆在t=0时是否连续?如果不检查P1实际开始的位置,并将起点从0转换为P1,终点转换为360+P1。感谢您的回复,但在这种情况下,该区域不是P1->P1+360度的整个圆吗?是的。这不是代码的目的吗?我不知道检测两个相交椭圆的逻辑,但是你的第一条线(for loop)告诉我你想在一个0到360的圆上循环。我不完全清楚遮挡的确切定义。当然,您还没有提到用于渲染的API。但我所知道的所有受C#支持的GUI API都包括使用某种类型的区域/形状进行剪裁。假设这是一个严格的渲染问题,您应该能够在渲染期间从剪辑区域中排除遮挡渲染椭圆的椭圆,并实现所需的效果。如果你能提供更多关于环境的细节,你可以给出一个真实的、详细的答案。我的理解是,虽然精确的解决方案是不可行的,但应该可以编写合理的代码,用数字方式解决这个方程。以下是一些看起来很有用的链接:,,如果你的问题是如何用另一个椭圆剪裁椭圆,请重新措辞。
      for (t=ang0;t<=ang1;t+=step)
       {
       if (t>=ang1) { t=ang1; e=1; } else e=0;
       ...
       if (e) break
       }