创造一个Squircle

时间:2009-12-07 23:58:01

标签: java swing drawing shapes

我是第一年的程序员。我正在努力创造一个松鼠。 (带圆角的方形)。

到目前为止,我已经成功了。我得到了a,b和r的常数。如果有人可以提供帮助,我会非常感激。我总是这么做菜。所以要好一点:)

package squircle;

import java.awt.*;
import javax.swing.*;
import java.lang.Math;

public class Main extends javax.swing.JApplet {

  public void paint(Graphics g){

   // (x-a)^4  +  (y-b)^4  = r^4

   //    y =   quadroot( r^4 - (x-a)^4  + b)     
   // x values must fall within   a-r < x < a+r

    int[] xPoints = new int[200];
    int[] yPoints = new int[200];
    int[] mypoints = new int[200];

    for(int c = 0; c <200; c++){

       int a = 100;
       int r = 100;
       int b = 100;
       double x = c ;


       double temp = (r*r*r*r);
       double temp2 = x-a;
       double temp3 = ((temp2)*(temp2)*(temp2)*(temp2));
       double temp6 = Math.sqrt(temp-temp3);
       double y = (Math.sqrt(temp6) + b );
       double z = (y*-1)+300;

       mypoints[c]=(int)z;

    // if (c>100){
    //     y = y*1;
    // }
    // else if(c<100){
    //     y = y*1;
    // }

       xPoints[c]=(int)x;
       yPoints[c]=(int)y;


    // change the equation to find x co-ordinates 
    // change it to find y co-ordinates. 

    // r is the minor radius     
    // (a,b) is the location of the centre

    // a = 100
    // b = 100
    // r = 100
    // x value must fall within  0 or 200

    }

    g.drawPolygon(xPoints, yPoints, xPoints.length);
    g.drawPolygon(xPoints, (mypoints), xPoints.length);
  }
}

5 个答案:

答案 0 :(得分:4)

是作业还是还有其他原因导致你没有使用Graphics#drawRoundRect()

答案 1 :(得分:4)

如果您将此作为家庭作业提交,则有一些风格元素可以帮助您。 200,100和300的作用是什么?这些是应该避免的“魔术常数”。它们是相关的还是它们具有这些价​​值的机会?建议您使用符号,如:

int NPOINTS = 200;

double radius = 100.0

这将揭示300实际上是否是您想要的价值。我没有检查过。

我个人不会写

y*-1

-y

因为错误输入前者太容易了。

我还打印出200个点作为浮点数,看看你是否可以通过眼睛看出错误的位置。虚假线很可能是在计算的开始或结束时绘制的 - 很容易产生“末端效应”错误,其中只有一个点被省略或计算两次。

实验也很便宜。尝试迭代c从0到100.或0到10,或0到198或1到200.你的假线/三角总是出现吗?

更新以下是我认为错误以及如何解决的问题。您已经发生了一个非常自然的图形错误和一个fence-post错误(http://en.wikipedia.org/wiki/Off-by-one_error),并且很难检测到错误,因为您的变量名称选择不当。

什么是mypoints?我相信它是松鼠的一半底部 - 如果你把它称为bottomHalf那么那些回复的woulod已经更快地发现了问题:-)。

你的图形问题在于你正在绘制两个HALF-squircles。您正在绘制CLOSED曲线 - 当您到达最后一个点(c == 199)时,通过绘制回到c == 0来关闭多边形。这使得D形。你有两个D形,一个凸起UP和一个DOWN。每个都有一条关闭多边形的水平线。

你的栅栏贴错误是你从0到199绘制点。对于你想要从0到200抽出的半节。这是201点!丢失一点意味着你有一个非常轻微的倾斜线。底线在与顶部相反的方向上倾斜。这给你一个非常楔形的形状,你称之为三角形。我猜你的三角形实际上并没有被关闭,而是像一个馅饼切片,但非常那么尖锐。

(下面的代码可能更漂亮,更紧凑。但是,将对称问题分解为象限或八分圆通常很有用。使用anngle扫描多边形也很有意思。)

你真的想要一个多边形。代码应该是这样的:

int NQUADRANT = 100;
int NPOINTS = 4*NQUADRANT ; // closed polygon
double[] xpoints = new double[NPOINTS];
double[] ypoints = new double[NPOINTS];

你的松鼠是100,100,半径为100.我在这里选择了不同的值 强调他们没有关系。通过使用符号名称,您可以轻松地改变它们。

double xcenter = 500.0;
double ycentre = 200.0;
double radius = 100.;

double deltax = radius/(double) NQUADRANT;
// let's assume squircle is centered on 0,0 and add offsets later
// this code is NOT complete or correct but should show the way
// I might have time later
for (int i = 0; i < NPOINTS; i++) {

if (i < NQUADRANT) {
    double x0 = -radius + i* deltax;
    double y0 = fourthRoot(radius, x0);
    x[i] = x0+xcenter;
    y[i] = y0+ycenter;

}else if (i < 2*NQUADRANT) {
    double x0 = (i-NQUADRANT)* deltax;
    double y0 = fourthRoot(radius, x0);
    x[i] = x0+xcenter;
    y[i] = y0+ycenter;
}else if (i < 3*NQUADRANT) {
    double x0 = (i-2*NQUADRANT)* deltax;
    double y0 = -fourthRoot(radius, x0);
    x[i] = x0+xcenter;
    y[i] = y0+ycenter;
}else {
    double x0 = -radius + (i-3*NQUADRANT)* deltax;
    double y0 = -fourthRoot(radius, x0);
    x[i] = x0+xcenter;
    y[i] = y0+ycenter;
}

}
// draw single polygon

private double fourthRoot(double radius, double x) {
    return Math.sqrt(Math.sqrt(radius*radius*radius*radius - x*x*x*x));
}

答案 2 :(得分:0)

有一个javascript版本here。您可以查看来源和“比较注释”,看看您做错了什么。

答案 3 :(得分:0)

好的,经过进一步调查,这就是为什么你得到“三角形相交”的原因。绘制多边形时,绘制点,最后一个点连接第一个点,关闭点并制作多边形。由于你绘制了一半,它被绘制(然后连接到自身),然后另一边也会发生相同的情况。

作为此次更改的测试,您的最后几行改为:

  for( int i = 0; i < yPoints.length; i++ ) {
   g.drawString( "*", xPoints[ i ], yPoints[ i ] );
  }

  for( int i = 0; i < mypoints.length; i++ ) {
   g.drawString( "*", xPoints[ i ], mypoints[ i ] );
  }

//  g.drawPolygon( xPoints, yPoints, xPoints.length );
//  g.drawPolygon( xPoints, ( mypoints ), xPoints.length );

这有点粗糙,但我想你会明白这一点。有很多解决方案,我个人会尝试使用Point类的数组,然后在完成后对其进行排序,但我不知道你能做什么和不能做什么的具体细节。

答案 4 :(得分:0)

哇,你们这些人是不是在想这个,或者是什么!为什么不使用drawLine()四次绘制矩形的直线部分,然后使用drawArc()绘制圆角?