1

我正在尝试做的事情

遍历两个轴并生成一个宽度和高度小于或等于嵌套 for 循环长度的形状,并计算从所有位置到该形状中心的距离。

主要问题)

  1. 如何使用与该椭圆不同尺寸的嵌套 for 循环指定要绘制的椭圆形状的宽度和高度?

例如一个嵌套的 for 循环,它在 X 轴上为 0 到 45,在 Y 轴上为 0 到 100,但绘制一个宽度为 39,高度为 90 的椭圆 - 剩余的差异用作填充(3两侧,顶部和底部各 5 个)。

我使用下面的 EdgeOrInBounds 函数进行了这一半工作,但是我无法理解为什么我使用的值给出了它们的结果。

使用与上面相同的嵌套 for 循环,但指定一个宽度为 30 且高度为 70 的椭圆没有预期的填充,而是绘制一个只有一个额外精灵围绕所有边的椭圆。

  1. 如何计算从椭圆中心到嵌套 for 循环生成的位置的距离,作为 0 到 1 之间的值?

例如,椭圆外的任何位置都返回零值,椭圆内的任何位置都返回从椭圆中心到 0 到 1 之间的距离。

与上面类似,我有这一半工作,因为我可以为椭圆外的所有位置返回零值,但我不明白如何缩放椭圆内位置的距离。

奖金问题

我在一个代码不易共享且内置函数很少的平台上执行此操作,因此我不得不根据来自 Nvidia 开发人员网站的示例创建自己的版本

我对一些 C# 和 JavaScript 有基本的了解,但对数学公式的了解为零。


椭圆函数

bool EdgeOrInBounds (Vector2 position) {
    int x = ((int) Math.Pow (position.x - center.x, 2) / (int) Math.Pow (radius.x, 2));
    int y = ((int) Math.Pow (position.y - center.y, 2) / (int) Math.Pow (radius.y, 2));

    return (x + y <= 1);
}

距离函数

float distance (Vector2 position) {
    return (sqrt (dot (centerPosition - position, centerPosition - position));
}

float dot (Vector2 a, Vector2 b) {
    return (a.x * b.x + a.y * b.y);
}

float sqrt (float a) {
    return (1.0 / pow (a, -0.5));
}

变量

int mapWidth  = 45;
int mapHeight = 100;


Vector2 radius = new Vector2 (mapWidth - 8, mapHeight - 4);
Vector2 center = new Vector2 (mapWidth / 2, mapHeight / 2);

嵌套 For 循环

for (int x = 0; x < width; x ++) {
    for (int y = 0; y < height; y ++) {
        // Store current position to reference in a minute
        Vector2 position = new Vector2 (x, y);

        // Check if position is within bounds or lies on the edge of the ellipse
        if (EdgeOrInBounds (position)) {
            // Calculate distance from center to current position
            float dist = distance (position);
        }
    }
}

示例图片

对我正在尝试做的事情的艺术诠释。

闭幕致辞

我知道我没有很好地解释我想要实现的目标,所以我想提前道歉,我还要感谢任何阅读本文的人,非常感谢任何帮助.

干杯

4

1 回答 1

0

为了更好地控制颜色阴影,您可以使用椭圆螺旋而不是方形网格遍历。从两个半径开始,使用 X=R1 * Cos(angle) 和 Y=R2 * Sin(angle),您逐渐将 R1 和 R2 减小到零。您的循环将使用极坐标(角度,r),见下文。然后你就可以确定你的“情节”的大小,你不需要测试正在进行的距离。它可能不需要任何距离函数来进行颜色缩放,但我不确定如何正确地做到这一点。我提供了一些选项。

        // The image is 440x240, I want ellipse in the center, margins 20 pix
        // Parameters, dependent on size and shape of elllipse

        Point pc = new Point(220,120); // pixel center
        double r1=200;                 // radius 1 margin 2x20 on 440
        double r2=100;                 // radius 2 margin 2x20 on 240

        // Covering all pixels
        int rmax = (int)Math.Max(r1,r2);

        // scaling for color
        var ravgmax = (r1+r2)/2.0;

        // Find suitable loop counts
        var nr = rmax;           // number of radius steps in loop
        var nh = 2*nr*Math.PI);  // number of angles in loop

        // Prepare initial loop displacements
        var h=0.0;
        var dr1 = r1/(nr*nh);
        var dr2 = r2/(nr*nh);
        var dh=(Math.PI*2.0)/nh;

        // The loop
        for (int i=0; i<nr; i++)
        {
            for (int j=0; j<(int)nh; j++)
            {
                var p = new PointF((float)(pc.X+r1*Math.Cos(h)),(float)(pc.Y+r2*Math.Sin(h)));

                // vanilla shading
                // int grayscale = 255 - (int)(255 * ((r1+r2)/2.0)/ravgmax );

                // elliptical option without using distance, scale along axes
                // grayscale = 255 - (int)(Math.Abs(p.X-pc.X)*255/200+Math.Abs((p.Y-pc.Y)*255/100)/2;

                // "Distance grayscale" which is circular, not elliptical
                int grayscale = (int)(255 * floatFDistance(p,pc)/rmax);
                
                PlotF(p,grayscale); // you provide: plotpixel(PointF, int)

                r1-=dr1; r2-=dr2;
                h+=dh;
            }
        }  

    }

    float floatFDistance(PointF p1, PointF p2)
    {
        double d1 = (p1.X - p2.X); 
        double d2 = (p1.Y - p2.Y);
        return (float)(Math.Sqrt(d1 * d1 + d2 * d2));
    }
于 2021-05-05T12:24:18.930 回答