1

I am trying to save some data as an STL file for use on a 3D printer. The STL file has two forms: ASCII and Binary. The ASCII format is relatively easy to understand and create but most 3D printing services require it to be in binary format.

The information about STL Binary is explained on the Wikipedia page here: http://en.wikipedia.org/wiki/STL_(file_format)

I know that I will require the data to be in a byte array but I have no idea how to go about interpreting the information from Wikipedia and creating the byte array. This is what I would like help with.

The code I have so far simply saves an empty byte array:

byte[] bytes = null;
FileOutputStream stream = new FileOutputStream("test.stl");
    try {
        stream.write(bytes);
    } finally {
        stream.close();
}
4

4 回答 4

1

如果您在最新的 Java 版本上开始一个新项目,您不应该为 OutputStreams 烦恼。请改用 Channels 和 ByteBuffers。

try(FileChannel ch=new RandomAccessFile("test.stl", "rw").getChannel())
{
  ByteBuffer bb=ByteBuffer.allocate(10000).order(ByteOrder.LITTLE_ENDIAN);
  // ...
  // e.g. store a vertex:
  bb.putFloat(0.0f).putFloat(1.0f).putFloat(42);
  bb.flip();
  ch.write(bb);
  bb.clear();
  // ...
}

这是唯一一个根据需要为您提供 little-endian 支持的 API。然后匹配数据类型:UINT8表示unsigned byte,UINT32表示unsigned int,REAL32表示float,UINT16表示unsigned short,REAL32[3]表示三个float(即一个数组)

只要不超过相应的有符号 Java 类型的最大值,您就不必担心数据类型的无符号性质。

于 2013-08-29T10:51:46.897 回答
1

这不应该如此模棱两可。规范说:

UINT8[80] – Header
UINT32 – Number of triangles

foreach triangle
  REAL32[3] – Normal vector
  REAL32[3] – Vertex 1
  REAL32[3] – Vertex 2
  REAL32[3] – Vertex 3
  UINT16 – Attribute byte count
end     

这意味着总文件大小为:80 + 4 + 三角形数 * ( 4 * 3 * 4 + 2 )。

例如,100 个三角形( 84+100*50 )会生成一个 5084 字节的文件。

您可以优化以下功能代码。打开文件并写入标题:

        RandomAccessFile raf = new RandomAccessFile( fileName, "rw" );
        raf.setLength( 0L );
        FileChannel ch = raf.getChannel();

        ByteBuffer bb = ByteBuffer.allocate( 1024 ).order( ByteOrder.LITTLE_ENDIAN );

        byte titleByte[] = new byte[ 80 ];
        System.arraycopy( title.getBytes(), 0, titleByte, 0, title.length() );
        bb.put( titleByte );

        bb.putInt( nofTriangles );              // Number of triangles

        bb.flip();                              // prep for writing
        ch.write( bb );

在此代码中,点顶点和三角形索引位于如下数组中:

Vector3 vertices[ index ]
int indices[ index ][ triangle point number ]

写入点数据:

        for ( int i = 0; i < nofIndices; i++ )  // triangles
        {
            bb.clear();
            Vector3 normal = getNormal( indices[ i ][ 0 ], indices[ i ][ 1 ], indices[ i ][ 2 ] );
            bb.putFloat( normal[ k ].x );
            bb.putFloat( normal[ k ].y );
            bb.putFloat( normal[ k ].z );
                
            for ( int j = 0; j < 3; j++ )           // triangle indices
            {
                bb.putFloat( vertices[ indices[ i ][ j ] ].x );
                bb.putFloat( vertices[ indices[ i ][ j ] ].y );
                bb.putFloat( vertices[ indices[ i ][ j ] ].z );
            }
            bb.putShort( ( short ) 0 );             // number of attributes
            bb.flip();
            ch.write( bb );
        }

关闭文件:

        ch.close();

获取法线:

Vector3 getNormal( int ind1, int ind2, int ind3 )
{
    Vector3 p1 = vertices[ ind1 ];
    Vector3 p2 = vertices[ ind2 ];
    Vector3 p3 = vertices[ ind3 ];
    return p1.cpy().sub( p2 ).crs( p2.x - p3.x, p2.y - p3.y, p2.z - p3.z ) ).nor();
}

也可以看看:

矢量3

于 2020-08-08T17:32:17.483 回答
0

您应该以 ASCII 格式生成此文件并使用 ASCII 到二进制 STL 转换器。

如果您自己无法回答这个问题,那么首先在 ascii 中完成可能会更容易。

http://www.thingiverse.com/thing:39655

于 2013-08-29T10:40:42.917 回答
0

由于您的问题是基于编写要发送到 3D 打印机的文件,我建议您放弃 STL 格式文件并改用 OBJ 格式文件。编写起来要简单得多,并且生成的文件要小得多。OBJ 没有二进制风格,但正如您将看到的,它仍然是一个非常紧凑的文件。

(缩写)规范说:

List all the geometric vertex coordinates as a "v", followed by x, y, z values, like:
    v 123.45 234.56 345.67

then List all the triangle as "f", followed by indices in a CCW order, like:
    f 1 2 3

Indices start with 1.
Use a # character to start a comment line. Don't append comments anywhere else in a line.
Blank lines are ok.

它还支持很多其他的东西,比如法线和纹理。但是,如果您只想将几何图形写入文件以导入 3D 打印机,那么 OBJ 实际上是首选,而且这个简单的内容是有效且足够的。

这是一个组成 1 单位立方体的完全有效文件的示例,已成功导入 Microsoft 3D Viewer(包含在 Win/10 中)、AutoDesk MeshMixer(免费下载)和 PrusaSlicers(免费下载)

# vertices
v 0 0 0
v 0 1 0
v 1 1 0
v 1 0 0
v 0 0 1
v 0 1 1
v 1 1 1
v 1 0 1
# triangle indices
f 1 3 4
f 1 2 3
f 1 6 2
f 1 5 6
f 1 8 5
f 1 4 8
f 3 7 8
f 3 8 4
f 3 6 7
f 2 6 3
f 5 8 7
f 5 7 6

如果您有多个网格中的数据,则应该合并顶点以消除重复点。但由于文件是纯文本,您可以使用 PrintWriter() 对象和 println() 方法来编写整个文件。

于 2020-08-10T09:35:42.147 回答