如何获得圆联合周长的点数组

时间:2014-01-21 13:44:15

标签: c# opengl math unity3d geometry

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

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

从中可以很容易地从周围得到一点...

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

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

(如果你必须使用它的集体参数方程的参数迭代它,以获得每个顶点所需的密度,那将是最好的。)

警告!结果只是一系列点(任何密度)与线相互连接(粗体黑色部分)。不是多边形。形状没有填满。

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

3 个答案:

答案 0 :(得分:4)

因为你知道Circle c1:

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

你想要额外的条件点P [x1,y1]∉任何其他C. 只需生成所有圆(或生成时检查条件)并删除所有更靠近任何中心[cx,cy]然后相应圆半径R的点。 要计算ditance(或更好的平方距离并与预先计算的平方R进行比较以改善穿孔),只需测量向量P的距离 - 中心(毕达哥拉斯):

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 (正确的一个 - 它开始变得复杂)。在addtiotion中,如果你需要保持正确的顺序,应该可以继续生成一个圆圈,直到你到达一个交叉点 - 然后切换圆圈为新的等等。 Carefull虽然:你需要从外形开始!

答案 1 :(得分:3)

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

对于着色器解决方案,您可以check here

#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); 
}

并稍微调整一下

答案 2 :(得分:1)

您的问题并不完整,因为您没有解释您希望如何将点分布在大纲上。我推断你想要沿着一条曲线排列密集的点序列。

这个问题没有简单的解决办法,结果形状可能非常复杂(甚至可能有洞)。你不会忘记计算圆弧和其他几何问题之间的交叉点。

解决这个问题的一种方法是使用足够的点密度对圆进行多边形化,并使用多边形联合算法。想到了优秀的Clipper库(http://www.angusj.com/delphi/clipper.php)。

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