如何获取圆环周长上的点的数组

5

我知道一个圆的参数方程是:

x = cx + r * cos(a)
y = cy + r * sin(a)

从这个圆心可以轻松得到一个点...

但是如果我想要获取许多相交圆的周长的数组点呢? 就像这样: Intersected circles

那么如果我知道每个圆的中心和半径,我该如何在坐标系中绘制包含(顶点,顺序很重要)的类似圆形联合的GL线呢?

(最好通过使用其集体参数方程的参数进行迭代,以获得所需密度的每个顶点。)

警告!结果只是由点(任意密度)组成的数组,它们按照彼此的顺序链接起来(粗黑色部分)。不是多边形。形状未填充。

(我想使用C#和GL.Lines在Unity3D中绘制它。)


你有多少个循环?5个,500个,50000个? - user1196549
1 ~ 100 可以互相淡入淡出。 - Z4urce
3个回答

4

既然您已经了解了 Circle c1:

x1 = cx1 + r1 * cos(a)
y1 = cy1 + r1 * sin(a)

如果您想要额外的条件点P[x1,y1]不属于任何其他圆C,请生成所有圆(或在生成时检查条件)并删除所有距离任何Center[cx,cy]更近的点,然后对应的圆半径R。为了计算距离(或更好地计算平方距离并与预先计算的平方R进行比较以提高性能),只需测量向量P-Center的距离(勾股定理):

foreach (Point p){
 foreach (other Circle c){
 float dist = (P - Center).Lenght;
 if (dist < c.R){
  // point is not valid, remove
 }
 }
}

这个解决方案并不是最优(如评论中所述)。 另一种方法是计算每个圆与其他每个圆的交点(https://math.stackexchange.com/questions/256100/how-can-i-find-the-points-at-which-two-circles-intersect),并删除这些点之间的RANGE(当然是右边的 - 这开始变得复杂了)。此外,如果您需要保持正确的顺序,应该可以继续生成一个圆直到达到交点 - 然后切换新圆等。 但要小心:必须从形状外部开始!


1
确实很好,但可能对计算来说有点太重了。 - Citrus
确实很重 - 你正在检查碰撞。但是,如果你计算平方距离而不是距离,并且预先计算平方R,那么你就可以避免执行sqrt()。 - wondra
这可能是一个不错的解决方案,但我认为它会破坏点的顺序。当我们想要将它们链接在一起时,这一点非常重要,否则结果将与我的图片上的不同:/ - Z4urce
@Z4urce 你可以计算交点并生成点,直到到达一个交点,然后切换圆并继续在新圆上进行,直到到达另一个交点等等。但这听起来需要大量的数学运算... - wondra
是的,我几乎绝望了。问题不在于跳到下一个圆圈,而是当您还不知道任何点时,只能根据用于计算它的角度存储这些点。在我们删除未使用的点之后,我们从零派开始绘制。当我们穿过圆圈时,我们跳过已删除的点,GL将上一个使用的点与当前点链接。此后,新绘制的圆圈看起来像我们从中切了一片...希望我表达清楚了 :/ - Z4urce
你需要正确连接这些部分(也就是要匹配序列类似的终点并将其合并起来),但如果需要精度,则此过程可能会很危险。或者你可以预先计算交点并从“安全”点(即没有在任何圆内的点)开始生成点,直到到达交点-切换圆。这意味着你需要找到正确的新起始角度(交点在另一个圆上的角度),并从那里开始在新圆上继续。 - wondra

3

根据您想要使用的OpenGL版本,一种简单的方法是在模板中跟踪每个圆的三角形。然后在不包括模板区域的线条中跟踪相同的圆。

对于着色器解决方案,您可以在此处检查

#ifdef GL_ES
precision mediump float;
#endif

uniform vec3      iResolution;           // viewport resolution (in pixels)
uniform float     iGlobalTime;           // shader playback time (in seconds)
uniform float     iChannelTime[4];       // channel playback time (in seconds)
uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click
uniform samplerXX iChannel0..3;          // input channel. XX = 2D/Cube
uniform vec4      iDate;                 // (year, month, day, time in seconds)
uniform float     iSampleRate;           // sound sample rate (i.e., 44100)

bool PixelInsideCircle( vec3 circle )
{
    return length(vec2(gl_FragCoord.xy - circle.xy)) < circle.z;
}

bool PixelOnCircleContour( vec3 circle )
{
    return PixelInsideCircle(circle) && !PixelInsideCircle( vec3(circle.xy,circle.z-1.0) );
}

void main( void )
{
    float timeFactor = (2.0+sin(iGlobalTime))/2.0;

    const int NB_CIRCLES=3;
    vec3 c[NB_CIRCLES];
    c[0] = vec3( 0.6, 0.4, 0.07 ) * iResolution;
    c[1] = vec3( 0.45, 0.69, 0.09 ) * iResolution;
    c[2] = vec3( 0.35, 0.58, 0.06 ) * iResolution;
    c[0].z = 0.09*iResolution.x*timeFactor;
    c[1].z = 0.1*iResolution.x*timeFactor;
    c[2].z = 0.07*iResolution.x*timeFactor;

    c[0].xy = iMouse.xy;

    bool keep = false;
    for ( int i = 0; i < NB_CIRCLES; ++i )
    {
        if ( !PixelOnCircleContour(c[i]) )
            continue;

        bool insideOther = false;
        for ( int j = 0; j < NB_CIRCLES; ++j )
        {
            if ( i == j )
                continue;

            if ( PixelInsideCircle(c[j]) )
                insideOther = true;
        }

        keep = keep || !insideOther;
    }

    if ( keep )
        gl_FragColor = vec4(1.0,1.0,0.0,1.0); 
}

并对其进行微调


抱歉如果我说得不够清楚,但我需要一个没有任何三角形或多边形的解决方案。只有点(顶点)。 (这些圆不存在,我们只知道它们的中心和半径。) - Z4urce
1
在这种情况下,你可以使用一个简单的着色器来丢弃掉落在三个圆内部的任何线段。我不确定你的问题是否属于OpenGL。 - Jean-Simon Brochu
我更新了我的着色器,这样我们就可以移动其中一个圆并且它们的半径会变化。 - Jean-Simon Brochu

1

由于您没有解释想要如何分布轮廓上的点,因此您的问题并不完整。我推断您希望沿着单一曲线有密集的点序列。

这个问题并没有简单的解决方案,导致的形状可能非常复杂(甚至可能有洞)。您无法避免计算圆弧与其他几何问题之间的交点。

解决的方法之一是将圆多边形化,并使用多边形联合算法。优秀的Clipper库就能胜任(http://www.angusj.com/delphi/clipper.php)。

另一种更快速而粗糙的解决方案是在栅格空间中工作:创建一个大的白色图像,并将所有圆都涂成黑色。然后使用轮廓跟随算法,如Moore-neighborhood算法(http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/index.html)。


实际上,我想要一个沿着单一曲线排序的点序列。 那个Clipper库真是太棒了。正如你已经发现的那样,我只需要从我的复杂形状(图像上的粗黑色)的周长中获取顶点。我该如何使用Clipper库来实现这一点? - Z4urce
就像之前所说的那样,将你的圆形转换成多边形并使用Clipper取它们的并集。Clipper会给你顶点。 - user1196549
我如何之后移除内部面和边缘? - Z4urce
你不需要这样做。Clipper的输出是顶点列表。 - user1196549
它们是否有序?我能用GL线迭代它们并获取复杂对象的轮廓吗? - Z4urce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接