我必须画一个椭圆,从第四象限开始,基于中点算法。我有一个代码,它从第一个,但我不明白如何修改公式,使它与第四个。我在想简单的倒转Y轴,但这是我的老师不允许的(太容易)。:/
void ellipseMedianMiniProjet(MyGrillePixels & g, int xC, int yC, int a, int b){
// Quatrième quadrant
int x=0, y=b, d, deltaE, deltaSE;
int b2=b*b, a2=a*a;
d = 4*b2 - a2*(1-4*b);
g.allumerPixel(0+xC,b+yC,126,20,251); // Allumage du promier et de ses 3 symétriques
g.allumerPixel(0+xC,-b+yC,126,20,251);
g.allumerPixel(a+xC,0+yC,126,20,251);
g.allumerPixel(-a+xC,0+yC,126,20,251);
while(2*b2*(x+1) < a2*(2*y-1)){ // 1ère région
if(d<0){ // Mouvement vers l'est
d+=b2*(8*x+12);
x++;
}else{ // Mouvement vers Sud Est
d+= b2*(8*x+12)+8*a2*(1-y);
x++; y--;
}
g.allumerPixel(x+xC,y+yC,126,20,251);
//g.allumerPixel(-x+xC,y+yC,126,20,251);
//g.allumerPixel(-x+xC,-y+yC,126,20,251);
//g.allumerPixel(x+xC,-y+yC,126,20,251);
}
// 2ème région
d = b2*(2*x+1)*(2*x+1) + 4*a2*(y-1)*(y-1)-4*a2*b2;
while(y>0){
if(d<0){ // Mvt SE
d+= a2*(12-8*y)+b2*(8*x+8);
x++;
y--;
}else{ // Mvt S
d+= a2*(12-8*y);
y--;
}
g.allumerPixel(x+xC,y+yC,126,20,251);
//g.allumerPixel(-x+xC,y+yC,126,20,251);
//g.allumerPixel(-x+xC,-y+yC,126,20,251);
//g.allumerPixel(x+xC,-y+yC,126,20,251);
}
while(x<a){
g.allumerPixel(x+xC,y+yC,126,20,251);
//g.allumerPixel(-x+xC,y+yC,126,20,251);
//g.allumerPixel(-x+xC,-y+yC,126,20,251);
//g.allumerPixel(x+xC,-y+yC,126,20,251);
x++;
}}
密码是法文的。A表示x半径,b y半径。我如何改变阿尔戈从第四象限开始?
提前寻求帮助。
发布于 2022-04-01 20:34:31
这应该做的工作,我使用这个算法在几年前在DOS下的图形。这是非常快的时间,它应该仍然是。
我假设"allumerPixel“作为参数,X和Y坐标,然后是(R,G,B)三重奏。您应该将它作为参数传递给您的函数,作为一个结构和/或元组,这样会更方便。
从全局上讲,该算法依赖于以下公式:
x 2/Rx 2+y 2/Ry 2=1
我让您对数学做详细说明,但是在搜索y (y=sqrt(Ry²*(1-(x²/Rx²))))时,很容易得到y(x+1) (y=sqrt(Ry²*(1-(x²/Rx²)))),并且知道函数y(x),就可以得到增量。
此外,为了避免代价高昂的平方根,用正方形代替方程更容易处理。显然,图是根据正确的值进行的,只有偏差检验是用平方进行的:知道x是阳性的,测试x>sqrt(a)或x²>a也是一样的。
我无法测试代码,因为我没有您的MyGrillePixels对象,而且我现在也没有时间设置一个可绘制的测试程序。但这应该管用。
如果您需要填充椭圆,则可以在while块中填充。我留下了一些评论来说明在哪里。
// Rx and Ry must be positive, in fact, code should enforce this precondition.
void Ellipse ( MyGrillePixels& g, int X, int Y, int Rx, int Ry )
{
int Yr = -Ry ; // TAKE CARE: Using a negative number here is the key for below tests AND the direction of the "for" loop, don't change it.
long long int Acc = -1 ; // Accumulator
long long int Rx2 = Rx*Rx ; // Used to get (Rx/Ry)²
long long int Ry2 = Ry*Ry ; // Can also use a double for precision, but it defeats Bresenham's algorithm to use only integers.
// Parse the first quadrant (trigonometric, so top-right quadrant).
for (int Xr = 0 ; Xr<=Rx ; Xr++) {
// Plot horizontally, use the 4 possible symmetries.
g.allumerPixel(X+Xr,Y+Yr,126,20,251);
g.allumerPixel(X-Xr,Y+Yr,126,20,251);
g.allumerPixel(X+Xr,Y-Yr,126,20,251);
g.allumerPixel(X-Xr,Y-Yr,126,20,251);
// Add to accumulator only the delta part
Acc += 2*Xr + 1 ;
// Test for a vertical "line", otherwise ellipse may not be complete.
// Do that either until we finished ellipse (Yr<0), or if we deviate too much (Acc>0).
while ((Acc>0) && (Yr<0)) {
// Start to plot vertically. Often reduced to one only pixel.
Yr++;
// Here: can draw an horizontal line from (X-Xr+1) to (X+Xr-1), line (Y+Yr).
// Color can be different from color used for border.
g.allumerPixel(X+Xr,Y+Yr,126,20,251);
g.allumerPixel(X-Xr,Y+Yr,126,20,251);
// Here: can draw an horizontal line from (X-Xr+1) to (X+Xr-1), line (Y-Yr).
g.allumerPixel(X+Xr,Y-Yr,126,20,251);
g.allumerPixel(X-Xr,Y-Yr,126,20,251);
// Compute deviation.
Acc += (Rx2*(2*Yr + 1)) / Ry2 ;
}
}
}此外,有一点建议,避免在您的代码中使用完整的法语,或完全英语,但避免将两者混合在一起。比如"ecrireData“或"readDonnees”。它很难看,而且无论如何,你不能用重音来表示法语单词,所以有时也很难读懂。我习惯于杀死我在公司代码中找到的每一个花花公子,因为这对每个人来说都是一种真正的痛苦。坚持英语,更易读.
https://stackoverflow.com/questions/71704115
复制相似问题