3

スタックオーバーフラワー、

Androidスマートフォンを使用して3Dフォームを作成する簡単なプロジェクトを行っています。Android Processing を使用してシンプルなアプリを作成しています。

私のコードは 3D 形状を作成し、.STL ファイルとして保存します。それは私のラップトップで動作し、.STL ファイルを保存しますが、アプリ内にあります。バージョン、携帯電話の外部ストレージ/SD カードに保存する必要があります (HTC Sensation)。私が使用している Processing ライブラリの「保存」関数 (writeSTL) が記述されているため、そうではありません。

ここに助けを求めて投稿しました(私のコードのより完全なコードもここにあります):

http://forum.processing.org/two/discussion/4809/exporting-geometry-stl-obj-dfx-modelbuilder-and-android

...そして、ライブラリを書いたマリウス・ワッツは、 writeSTL() コードはほとんどスタンドアロンであり、欠けているのは出力ストリームを作成するコードを置き換えることだけです (またはそうすべきです)。これは Android で動作するように変更する必要があります。基本的に、この行:

FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

私は通常、Processing に必要なことを実行させることはできますが、それ以上のことはできないという点で、優れたプログラマーではありません。この問題は私を打ち負かしました。行を置き換える正しいコードのアイデアを探しています:...

FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

...「Android にやさしい」何かを使って。getExternalStorageDirectory() の呼び出しは機能するはずですが、正しい構造を見つけることができません。

writeSTL 関数のコードは次のとおりです。

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Output binary STL file of mesh geometry.
 * @param p Reference to PApplet instance
 * @param filename Name of file to save to
 */

  public void customWriteSTL(UGeometry geo, PApplet p, String filename) {
  byte [] header;
  ByteBuffer buf;
  UFace f;

  try {
    if (!filename.toLowerCase().endsWith("stl")) filename+=".stl";
    FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

buf = ByteBuffer.allocate(200);
header=new byte[80];
buf.get(header, 0, 80);
out.write(header);
buf.rewind();

buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putInt(geo.faceNum);
buf.rewind();
buf.get(header, 0, 4);
out.write(header, 0, 4);
buf.rewind();

UUtil.logDivider("Writing STL '"+filename+"' "+geo.faceNum);

buf.clear();
header=new byte[50];
if (geo.bb!=null) UUtil.log(geo.bb.toString());

for (int i=0; i<geo.faceNum; i++) {
  f=geo.face[i];
  if (f.n==null) f.calcNormal();

  buf.rewind();
  buf.putFloat(f.n.x);
  buf.putFloat(f.n.y);
  buf.putFloat(f.n.z);

  for (int j=0; j<3; j++) {
    buf.putFloat(f.v[j].x);
    buf.putFloat(f.v[j].y);
    buf.putFloat(f.v[j].z);
  }

  buf.rewind();
  buf.get(header);
  out.write(header);
}

out.flush();
out.close();
UUtil.log("Closing '"+filename+"'. "+geo.faceNum+" triangles written.\n");
  } 
  catch (Exception e) {
e.printStackTrace();
  }
}

どんな提案もありがたく受け取られます。

前もって感謝します。

4

1 に答える 1

1

これを行うにはいくつかの方法があります - うまくいく方法と適切方法があります...すべての処理/Javaと同様です。ただし、実際には通常のJavaとそれほど違いはありません-唯一の癖は、ルートSDパスと、それが存在するかどうかを確認することです(一部の電話には「外部」ストレージではなく「内部」ストレージがあることに注意してください(つまり、リムーバブル/スワップ可能ではありません)。 Android は、これらの同じ AFAIK を解釈する必要があります。

古典的なJavaのやり方では、SDカードが存在するかどうかを事前に確認する必要があります... @kaolickによるこの回答から取得した次の構造を使用ます

    String state = Environment.getExternalStorageState();
    if (state.equals(Environment.MEDIA_MOUNTED)) {
        // Storage is available and writeable - ALL GOOD  
    } else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
        // Storage is only readable - RUH ROH
    } else {
        // Storage is neither readable nor writeable - ABORT    
    }

彼はあなたが使用できる完全なクラスを提供していることに注意してください。これは素晴らしいことであり、便利な機能がいくつかあります。

次に確認したいのは、おそらく setup() で、デバイスの SD カードにカスタム ディレクトリを作成することです。次のようなものです。

  try{
    String dirName = "//sdcard//MyAppName";
    File newFile = new File(dirName);

    if(newFile.exists() && newFile.isDirectory()) {
      println("Directory Exists... All Good");
    } 
    else {
      println("Directory Doesn't Exist... We're Making It");
      newFile.mkdirs();
    }
  }
  catch(Exception e) {
    e.printStacktrace();
  }

もちろん、パス名をハードコーディングする代わりに、次のようにする必要があります

String dirName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppName";

代わりは...

また、上記の try/catch は、「if (state.equals(Environment.MEDIA_MOUNTED))」の case ステートメントの内側に移動する必要があることに注意してください ... または、そこから呼び出される別の関数 anc にラップする必要があります。

そして、最後に、それを保存します。BufferedWriter を使用する場合は、次のようになります。

  BufferedWriter writer = new BufferedWriter(new FileWriter(dirName, true));
  writer.write(STL_STUFF);
  writer.flush();
  writer.close();

私は BufferedOutput ストリーム内で FileOutputStream のみを使用しましたが、次のようになりました。

try {
    String fileName = "SOME_UNIQUE_NAME_PER_FILE";
    String localFile = dirName + "/" +filename;
    OutputStream output = new BufferedOutputStream(newFileOutputStream(localFile));
}
catch(Exception e) {
    e.printStackTrace();
}

最後に、マリウスと話せたらよろしくね!;-)

于 2014-06-29T19:05:22.957 に答える