如何将二十面体细分为球体

How to subdivide an icosahedron into a sphere

我正在尝试为我正在处理的 Java Applet 项目生成一个 icosphere。我有一个用于二十面体的工作细分,但是一旦我尝试将它投影到一个单位球体上,它就会创建一个尖尖的网格。 我在网上寻找正确投影的解决方案,它说我应该使用以下公式: 归一化点=X/Y/Z值*半径/量级取点

我在单位球体上寻找新点的代码如下:

private Point3D createMiddlePoint(Point3D p1, Point3D p2){
    // not in cache, calculate it
    Point3D middle = new Point3D(
        (int)((p1.x + p2.x) / 2.0), 
        (int)((p1.y + p2.y) / 2.0), 
        (int)((p1.z + p2.z) / 2.0));

    // add vertex makes sure point is on unit sphere (Problem lies in these two statements)
    double magnitude = Math.sqrt(Math.pow(middle.x-centerX,2)+Math.pow(middle.y-centerY,2)+Math.pow(middle.z,2));
    middle = new Point3D((int)((double)middle.x *size/(double)magnitude), (int)((double)middle.y/(double)magnitude), (int)((double)middle.z/(double)magnitude));

    return middle;
}`

中心 X 和中心 Y 是 icosahedron/sphere 的中心,大小是二十面体的直径,我无法将变量整合到上面的公式中。

如有任何帮助,我们将不胜感激。

我发现我做错了什么。我假设我的大小变量是圆的直径,但实际上不是。因此,为了解决这个问题,我发现球体的直径实际上是 size*(1+Math.sqrt(5))/2,它与二十面体相交于 3 个点。从那里开始,我将下一个顶点缩小了 2/3,以便它仍然填充球形区域。代码如下: ` public void create(int recursionLevel) { int t = (int) (size*2/3 * (1.0 + Math.sqrt(5.0)) / 2.0);

    vertices.add(new Point3D((-size*2/3 + centerX),  t + centerY,  0));
    vertices.add(new Point3D( size*2/3 + centerX,  t + centerY,  0));
    vertices.add(new Point3D(-size*2/3 + centerX, -t + centerY,  0));
    vertices.add(new Point3D( size*2/3 + centerX, -t + centerY,  0));

    vertices.add(new Point3D( centerX, -size*2/3 + centerY,  t));
    vertices.add(new Point3D( centerX,  size*2/3 + centerY,  t));
    vertices.add(new Point3D( centerX, -size*2/3 + centerY, -t));
    vertices.add(new Point3D( centerX,  size*2/3 + centerY, -t));

    vertices.add(new Point3D( t + centerX,  centerY, -size));
    vertices.add(new Point3D( t + centerX,  centerY,  size));
    vertices.add(new Point3D(-t + centerX,  centerY, -size));
    vertices.add(new Point3D(-t + centerX,  centerY,  size));



    // 5 faces around point 0
    faces.add(new Triangle(vertices.get(0),vertices.get(11),vertices.get(5)));
    faces.add(new Triangle(vertices.get(0), vertices.get(5), vertices.get(1)));
    faces.add(new Triangle(vertices.get(0), vertices.get(1), vertices.get(7)));
    faces.add(new Triangle(vertices.get(0), vertices.get(7), vertices.get(10)));
    faces.add(new Triangle(vertices.get(0), vertices.get(10), vertices.get(11)));

    // 5 adjacent faces 
    faces.add(new Triangle(vertices.get(1), vertices.get(5), vertices.get(9)));
    faces.add(new Triangle(vertices.get(5), vertices.get(11), vertices.get(4)));
    faces.add(new Triangle(vertices.get(11), vertices.get(10), vertices.get(2)));
    faces.add(new Triangle(vertices.get(10), vertices.get(7), vertices.get(6)));
    faces.add(new Triangle(vertices.get(7), vertices.get(1), vertices.get(8)));

    // 5 faces around point 3
    faces.add(new Triangle(vertices.get(3), vertices.get(9), vertices.get(4)));
    faces.add(new Triangle(vertices.get(3), vertices.get(4), vertices.get(2)));
    faces.add(new Triangle(vertices.get(3), vertices.get(2), vertices.get(6)));
    faces.add(new Triangle(vertices.get(3), vertices.get(6), vertices.get(8)));
    faces.add(new Triangle(vertices.get(3), vertices.get(8), vertices.get(9)));

    // 5 adjacent faces 
    faces.add(new Triangle(vertices.get(4), vertices.get(9), vertices.get(5)));
    faces.add(new Triangle(vertices.get(2), vertices.get(4), vertices.get(11)));
    faces.add(new Triangle(vertices.get(6), vertices.get(2), vertices.get(10)));
    faces.add(new Triangle(vertices.get(8), vertices.get(6), vertices.get(7)));
    faces.add(new Triangle(vertices.get(9), vertices.get(8), vertices.get(1))); 

    Point3D a;
    Point3D b;
    Point3D c;
    for (int i = 0; i < recursionLevel; i++) {
        ArrayList<Face2D> faces2 = new ArrayList<Face2D>();
        while(faces.size() != 0){
            a = createMiddlePoint(faces.get(0).vertices[0], faces.get(0).vertices[1]);
            b = createMiddlePoint(faces.get(0).vertices[1], faces.get(0).vertices[2]);
            c = createMiddlePoint(faces.get(0).vertices[2], faces.get(0).vertices[0]);

            faces2.add(new Triangle(faces.get(0).vertices[0], a, c));
            faces2.add(new Triangle(faces.get(0).vertices[1], b, a));
            faces2.add(new Triangle(faces.get(0).vertices[2], c, b));
            faces2.add(new Triangle(a, b, c));
            faces.remove(0);
        }
      System.out.println("Recursion Level: " + i + ", Faces:" + faces2.size());
      //System.out.println("" + (System.currentTimeMillis() - startTime));
      faces = faces2;
    }
}

private Point3D createMiddlePoint(Point3D p1, Point3D p2){
    Point3D middle = new Point3D(
        (int)((p1.x + p2.x) / 2.0 - centerX), 
        (int)((p1.y + p2.y) / 2.0 - centerY), 
        (int)((p1.z + p2.z) / 2.0));
    if(radius == -1){
        radius = (size*(1.0 + Math.sqrt(5.0)))/2;
    }
    // add vertex makes sure point is on unit sphere (Problem lies in these two statements)
    double magnitude = Math.sqrt(Math.pow(middle.x,2)+Math.pow(middle.y,2)+Math.pow(middle.z,2));

    return new Point3D((int)((middle.x)*radius/magnitude) + centerX, (int)((middle.y)*radius/magnitude) + centerY, (int)(middle.z*radius/magnitude));
}

有关如何完成此操作的更多信息,请访问 http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html