【发布时间】:2014-06-15 00:47:48
【问题描述】:
在我的课堂上,我们的任务如下:
对于这项作业,您将尝试编写一个程序来计算一组形状的重叠区域,并实现蒙特卡罗积分,如课堂上所讨论的。 制作 AreaEstimator.java,这是一个使用随机估计来估计任意数量的圆形和三角形的重叠面积的程序。该程序的参数将是要在此试验中使用的随机生成的点的数量,然后是定义形状的点的坐标。例如,
java AreaEstimator 1000000 圆 2.0 2.0 1.0 三角形 1.0 1.0 2.5 3.0 2.0 -3.0 圆 2.5 1.0 3.0
将生成一百万个随机点来估计一个三角形的重叠,该三角形的顶点是 (1.0, 1.0), (2.5, 3.0), (2.0, -3.0),两个圆的中心在 (2.0, 2.0)和 ( 2.5, 1.0 ),其半径分别为 1.0 和 3.0。
这是我的 Circle 类代码:
public class Circle {
private double xcenter;
private double ycenter;
private double radius;
private double xcmax;
private double xcmin;
private double ycmax;
private double ycmin;
public Circle ( double xcenter, double ycenter, double radius){
if(radius <= 0){
throw new IllegalArgumentException();
}
this.xcenter = xcenter;
this.ycenter = ycenter;
this.radius = radius;
}
public void maxAndMinCircle (){ //find the minimun and maximum for the plane according to this circle
xcmax = (this.xcenter + this.radius);
ycmax = (this.ycenter + this.radius);
xcmin = (this.xcenter - this.radius);
ycmin = (this.ycenter - this.radius);
}
public double getXCMax (){
return xcmax;
}
public double getYCMax () {
return ycmax;
}
public double getXCMin() {
return xcmin;
}
public double getYCMin(){
return ycmin;
}
public boolean outsideCircle(double randX, double randY){ // find if the random point passed thru is in this circle
double distance = Math.sqrt((randX-this.xcenter)*(randX-this.xcenter) + (randY-this.ycenter) * (randY - this.ycenter));
return distance >= radius;
}}
三角形类:
public class Triangle {
private double cornerx1;
private double cornery1;
private double cornerx2;
private double cornery2;
private double cornerx3;
private double cornery3;
private double xtmax;
private double xtmin;
private double ytmax;
private double ytmin;
private Double[] corners;
public Triangle (double cornerx1, double cornery1, double cornerx2, double cornery2, double cornerx3, double cornery3){
corners = new Double [6];
corners[0] = cornerx1;
corners[1] = cornery1;
corners[2] = cornerx2;
corners[3] = cornery2;
corners[4] = cornerx3;
corners[5] = cornery3;
}
public void maxAndMinTriangle (){ // find the minimum and maximum of the plane according to this triangle
xtmax = corners[0];
for(int i=1;i < corners.length;i += 2){
if(corners[i] > xtmax){
xtmax = corners[i];
}
}
xtmin = corners[0];
for(int i=1;i < corners.length;i += 2){
if(corners[i] < xtmin){
xtmin = corners[i];
}
}
ytmax = corners[1];
for(int i=1;i < corners.length;i += 2){
if(corners[i] > ytmax){
ytmax = corners[i];
}
}
ytmin = corners[1];
for(int i=1;i < corners.length;i += 2){
if(corners[i] < ytmin){
ytmin = corners[i];
}
}
}
public double getXTMax (){
return xtmax;
}
public double getYTMax () {
return ytmax;
}
public double getXTMin() {
return xtmin;
}
public double getYTMin(){
return ytmin;
}
//public static boolean isLeft (double x1, double y1, double x2, double y2, double x3, double y3){
//return ( 0 <= ( ( x2 - x1 ) * ( y - y1) )- (( y2 - y1) * ( x - x1)));
//}
public boolean isLeft1 (double randX, double randY){ // find if this point is to the left of the first line
return ( 0 <= ( ( corners[2] - corners[0] ) * ( randY - corners[1]) )- (( corners[3] - corners[1]) * ( randX - corners[0])));
}
public boolean isLeft2 (double randX, double randY){ // find if this point is to the left of the second line
return ( 0 <= ( ( corners[4] - corners[0]) * ( randY - corners[1]) )- (( corners[5] - corners[1]) * ( randX - corners[0])));
}
public boolean isLeft3 (double randX, double randY){ // find if this point is to the left of the third line
return ( 0 <= ( ( corners[4] - corners[2] ) * ( randY - corners[3]) )- (( corners[5] - corners[3]) * ( randX - corners[2])));
}
public boolean outsideTriangle ( double randX, double randY ){ // find if this point is inside of the triangle
int counter = 0;
if (isLeft1(randX,randY)){
counter++;
}
if (isLeft2(randX,randY)){
counter++;
}
if (isLeft3(randX,randY)){
counter++;
}
return counter == 2; // must be to the left of exactly 2 of the lines
}}
然后是 AreaEstimator 类:
public class AreaEstimator{
public static double[] maxAndMinValues (Circle[] circles,Triangle[] triangles){
// find maximum and minimum values according to all of the triangles and circles
double xmax = -100;
double ymax = -100;
double xmin = 100;
double ymin = 100;
for (int l=0; l < circles.length; l++){
if (xmax < circles[l].getXCMax()){
xmax = circles[l].getXCMax();
}
if (ymax < circles[l].getYCMax()){
ymax = circles[l].getYCMax();
}
if (xmin > circles[l].getXCMin()){
xmin = circles[l].getXCMin();
}
if (ymin > circles[l].getYCMin()){
ymin = circles[l].getYCMin();
}
}
for ( int m = 0; m < triangles.length; m++){
if(xmax < triangles[m].getXTMax()){
xmax = triangles[m].getXTMax();
}
if(ymax < triangles[m].getYTMax()){
ymax = triangles[m].getYTMax();
}
if(xmin > triangles[m].getXTMin()){
xmin = triangles[m].getXTMin();
}
if(ymin > triangles[m].getYTMin()){
ymin = triangles[m].getYTMin();
}
}
double[] result = new double [4];
result[0] = xmax;
result[1] = ymax;
result[2] = xmin;
result[3] = ymin;
return result;
}
public static void main (String[] args) {
double numThrows = Integer.parseInt(args[0]); // initialize amount of throws
if (numThrows <= 0){
throw new IllegalArgumentException();
}
int countCircles = 0; // find the amount of circles given
for ( int i = 1; i<args.length; i++){
if(args[i].equals("circle")){
countCircles++;
}
}
Circle[] circles = new Circle [countCircles];
for ( int i = 1; i<args.length; i++){
if (args[i].equals("circle")){
for ( int k = 0; k< countCircles; k++){
double xcenter = Double.parseDouble(args[i+1]);
double ycenter = Double.parseDouble(args[i+2]);
double radius = Double.parseDouble(args[i+3]);
circles[k] = new Circle (xcenter, ycenter, radius); //values associated with this circle
circles[k].maxAndMinCircle();//max and min value of the circle itself
}
}
}
int countTriangles = 0; // find the amount of the triangles given
for ( int i = 1; i < args.length; i++){
if(args[i].equals("triangle")){
countTriangles++;
}
}
Triangle[] triangles = new Triangle [countTriangles];
for ( int i = 1; i<args.length; i++){
if (args[i].equals("triangle")){
for ( int p = 0; p< countTriangles; p++){
double cornerx1 = Double.parseDouble(args[i+1]);
double cornery1 = Double.parseDouble(args[i+2]);
double cornerx2 = Double.parseDouble(args[i+3]);
double cornery2 = Double.parseDouble(args[i+4]);
double cornerx3 = Double.parseDouble(args[i+5]);
double cornery3 = Double.parseDouble(args[i+6]);
triangles[p] = new Triangle (cornerx1, cornery1, cornerx2, cornery2, cornerx3, cornery3);
//values associated with this triangle
triangles[p].maxAndMinTriangle(); //max and min value of the triangle itself
}
}
}
boolean dartsInOverlap = true;
double countInOverlap = 0; // initialize amount of darts in the overlapping shape
double[]result = maxAndMinValues(circles,triangles);
for(int i= 0;i < numThrows;i++){
double randX= (Math.random() * (result[0]-result[2]) + result[2]) ; // generate a random x value
double randY= (Math.random() * (result[1]-result[3])+ result[3]); // generate a random y value
for ( int h = 0; h < circles.length && dartsInOverlap; h++){
if (circles[h].outsideCircle(randX, randY)){
dartsInOverlap = false; // if the point is outside of the circle, it returns false
}
}
for ( int q = 0; q < triangles.length && dartsInOverlap; q++){
if (triangles[q].outsideTriangle(randX, randY)){
dartsInOverlap = false; // if the point is outside of the triangle, it returns false
}
}
if (dartsInOverlap){
countInOverlap++; // counts up the amount of points in the overlapping shape
}
dartsInOverlap = true;
}
System.out.println("This many darts were in the overlap between the shapes:" + countInOverlap);
// counts up the amount of points in the overlapping shape
System.out.println("The estimated overlapped areas is" + (result[0]-result[2])*(result[1]-result[3]) *(countInOverlap/numThrows));
//finds estimated area
}}
如果在命令行中只输入了一个圆形和三角形,或者只有一个圆形,我的代码已经为几个测试用例工作过。一个三角形本身或任何其他组合会给我的答案与所需的面积估计相去甚远。我查看并审查了我的代码,这一切似乎都是合乎逻辑的。那么,在我的代码中,问题可能会持续存在吗?任何帮助,将不胜感激。
【问题讨论】: