packagetest_stl.test_entry;importjava.io.FileNotFoundException;importjava.io.IOException;importjava.io.RandomAccessFile;importjava.util.regex.Matcher;importjava.util.regex.Pattern;/*** 注意java byte范围-128~127

*

*@authorephuizi@gmail.com

**/

public classSTLUtils {//final private static Pattern ASCII_PATTERN_FACET =//Pattern.compile("facet([\\s\\S]*?)endfacet");

final private static Pattern ASCII_PATTERN_NORMAL =Pattern

.compile("normal[\\s]+([\\-+]?[0-9]+\\.?[0-9]*([eE][\\-+]?[0-9]+)?)+[\\s]+([\\-+]?[0-9]*\\.?[0-9]+([eE][\\-+]?[0-9]+)?)+[\\s]+([\\-+]?[0-9]*\\.?[0-9]+([eE][\\-+]?[0-9]+)?)+");final private static Pattern ASCII_PATTERN_VERTEX =Pattern

.compile("vertex[\\s]+([\\-+]?[0-9]+\\.?[0-9]*([eE][\\-+]?[0-9]+)?)+[\\s]+([\\-+]?[0-9]*\\.?[0-9]+([eE][\\-+]?[0-9]+)?)+[\\s]+([\\-+]?[0-9]*\\.?[0-9]+([eE][\\-+]?[0-9]+)?)+");/*** 判断是否stl格式

*

*@paramstlPath

*@returntrue binary false ascii*/

public static booleanisBinary(String stlPath) {long expect = 0;//以binnary方式计算的文件大小;

int face_size = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8);//一个三角片大小

int n_facetNum = 0;//三角片数量

RandomAccessFile stl = null;try{

stl= new RandomAccessFile(stlPath, "r");

stl.seek(80);byte[] arr = { 0, 0, 0, 0};

stl.read(arr);

n_facetNum=STLFaceNum(arr);

expect= 80 + (32 / 8) + (n_facetNum *face_size);if (expect ==stl.length()) {

stl.close();return true;

}//some binary files will have different size from expected,//checking characters lower than ASCII to confirm is binary

long fileLength =stl.length();

stl.seek(0);for (long index = 0; index < fileLength; index++) {if (stl.readByte() < 0) {

stl.close();return true;

}

}

stl.close();return false;

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}return false;

}/*** 用于正数,因为负数存储是补码 第81~84四个字节

*

*@paramarr

*@return

*/

public static int STLFaceNum(byte[] arr) {if (arr != null && arr.length == 4) {int a = arr[0] & (0xFF);//防止低位转二进制后是变成负数

int b = (arr[1] << 8) & (0xFFFF);int c = (arr[2] << 16) & (0xFFFFFF);int d = (arr[3] << 24) & (0xFFFFFFFF);return a + b + c +d;

}return -1;

}/*** resolve binary stl file

*

*@paramstlPath

*@return

*/

public staticSTLFile parseBinary(String stlPath) {

RandomAccessFile stl= null;try{

stl= new RandomAccessFile(stlPath, "r");

stl.seek(80);byte[] arr = { 0, 0, 0, 0};

stl.read(arr);int facetNum =STLFaceNum(arr);float r = 0, g = 0, b = 0;boolean hasColors = false;float[] colors = null;float defaultR = 0, defaultG = 0, defaultB = 0, alpha = 0;//process STL header//check for default color in header ("COLOR=rgba" sequence).

for (int index = 0; index < 80 - 10; index++) {

stl.seek(index);//6字节("COLOR=")

if (stl.readInt() == 0x434F4C4F /*COLO*/&& (stl.readByte() == 0x52 /*'R'*/)&& (stl.readByte() == 0x3D /*'='*/)) {

hasColors= true;

colors= new float[facetNum * 3 * 3];//一个面三个点每个点(r,b,g)

defaultR= STLUtils.toFloat(stl.readByte()) / 255;//6

defaultG = STLUtils.toFloat(stl.readByte()) / 255;//7

defaultB = STLUtils.toFloat(stl.readByte()) / 255;//8

alpha = STLUtils.toFloat(stl.readByte()) / 255;//9

break;

}

}int dataOffset = 84;int offset = 0;float[] vertices = new float[facetNum * 3 * 3];float[] normals = new float[facetNum * 3 * 3];//三角面片法向量的3个分量值数据

byte temp[] = { 0, 0, 0, 0};int max = 0;//第一个三角片z轴高度

boolean isBegin = true;

stl.seek(dataOffset);for (int face = 0; face < facetNum; face++) {//法向量12个字节

stl.read(temp);float normalX = STLUtils.toFloat(temp);//4

stl.read(temp);float normalY = STLUtils.toFloat(temp);//4

stl.read(temp);float normalZ = STLUtils.toFloat(temp);//4//顶点坐标36字节

for (int i = 1; i <= 3; i++) {

stl.read(temp);

vertices[offset]=STLUtils.toFloat(temp);

stl.read(temp);

vertices[offset+ 1] =STLUtils.toFloat(temp);

stl.read(temp);

vertices[offset+ 2] =STLUtils.toFloat(temp);if(isBegin) {

isBegin= false;

max= (int) (vertices[offset + 2]);

}

normals[offset]=normalX;

normals[offset+ 1] =normalY;

normals[offset+ 2] =normalZ;

offset+= 3;//增加位移

}//color2字节

if(hasColors) {int packedColor = STLUtils.toInt(stl.readByte()) | STLUtils.toInt(stl.readByte()) << 8 & 0xFFFF;if ((packedColor & 0x8000) == 0) { //facet has its own//unique color

r= (packedColor & 0x1F) / 31;

g= ((packedColor >> 5) & 0x1F) / 31;

b= ((packedColor >> 10) & 0x1F) / 31;

}else{

r=defaultR;

g=defaultG;

b=defaultB;

}

}else{//无颜色 丢弃2字节

stl.readByte();

stl.readByte();

}//补充颜色

if(hasColors) {

colors[face* 9 + 0] =r;

colors[face* 9 + 1] =g;

colors[face* 9 + 2] =b;

colors[face* 9 + 3] =r;

colors[face* 9 + 4] =g;

colors[face* 9 + 5] =b;

colors[face* 9 + 6] =r;

colors[face* 9 + 7] =g;

colors[face* 9 + 8] =b;

}

}

stl.close();return newSTLFile(max, facetNum, alpha, hasColors, vertices, normals, colors);

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}return null;

}public staticSTLFile parseASCII(String stlPath) {int facetNum =asciiFacetNum(stlPath);

RandomAccessFile stl= null;try{

stl= new RandomAccessFile(stlPath, "r");float[] vertices = new float[facetNum * 3 * 3];float[] normals = new float[facetNum * 3 * 3];//三角面片法向量的3个分量值数据

final String FACET_END = "endfacet";

StringBuffer bf= new StringBuffer();//record one-facet

int facetIndex = 0;

String line= null;while ((line = stl.readLine()) != null) {

bf.append(line);if (line.length() > 8 && line.length() < 15 &&line.contains(FACET_END)) {//one facet

String oneFacet =bf.toString();

Matcher nMatcher=ASCII_PATTERN_NORMAL.matcher(oneFacet);if (!nMatcher.find())continue;

String normal=nMatcher.group();

Matcher mV=ASCII_PATTERN_VERTEX.matcher(oneFacet);if (!mV.find())continue;

String v1= mV.group();//第一个顶点

if (!mV.find())continue;

String v2= mV.group();//第二个顶点

if (!mV.find())continue;

String v3= mV.group();//第三个顶点//解析法向量

String GAP = " ";int nfIndex = facetIndex * 9;

String[] n_f_arr=normal.split(GAP);

normals[nfIndex+ 6] = normals[nfIndex + 3] = normals[nfIndex] = Float.parseFloat(n_f_arr[1]);

normals[nfIndex+ 1 + 6] = normals[nfIndex + 1 + 3] = normals[nfIndex + 1] =Float

.parseFloat(n_f_arr[2]);

normals[nfIndex+ 2 + 6] = normals[nfIndex + 2 + 3] = normals[nfIndex + 2] =Float

.parseFloat(n_f_arr[3]);//解析顶点

String[] v1_f_arr =v1.split(GAP);

vertices[nfIndex+ 0] = Float.parseFloat(v1_f_arr[1]);//x

vertices[nfIndex + 1] = Float.parseFloat(v1_f_arr[2]);//y

vertices[nfIndex + 2] = Float.parseFloat(v1_f_arr[3]);//z

String[] v2_f_arr=v2.split(GAP);

vertices[nfIndex+ 3] = Float.parseFloat(v2_f_arr[1]);

vertices[nfIndex+ 4] = Float.parseFloat(v2_f_arr[2]);

vertices[nfIndex+ 5] = Float.parseFloat(v2_f_arr[3]);

String[] v3_f_arr=v3.split(GAP);

vertices[nfIndex+ 6] = Float.parseFloat(v3_f_arr[1]);

vertices[nfIndex+ 7] = Float.parseFloat(v3_f_arr[2]);

vertices[nfIndex+ 8] = Float.parseFloat(v3_f_arr[3]);//set bf count=0

facetIndex++;

bf.setLength(0);

}

}

stl.close();int max = (int) vertices[2];return new STLFile(max, facetNum, 0, false, vertices, normals, null);

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}return null;

}/*** 计算ascii-stl-file三角片数量

*

*@paramstlPath

*@return

*/

public static final intasciiFacetNum(String stlPath) {

RandomAccessFile stl= null;int facetNum = 0;try{

stl= new RandomAccessFile(stlPath, "r");int lineNum = 0;int c = 0;while (c != -1) {switch (c =stl.read()) {case -1:case '\n':

lineNum++;break;case '\r':

stl.read();//to skip '\n'

lineNum++;break;default:break;

}

}

facetNum= lineNum / 7;

stl.close();

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}returnfacetNum;

}/*** -1 原码1000,0001 反码1111,1110 补码1111,1111 所以无符号值 255

*

*@paramb

*@return

*/

public static int toInt(byteb) {return (int) (b & 0xFF);

}/*** -1 原码1000,0001 反码1111,1110 补码1111,1111 所以无符号值 255 带符号位

*

*@paramb

*@return

*/

public static float toFloat(byteb) {return (float) (b & 0xFF);

}/*** 字节转换为浮点

*

*@paramb

* 字节(至少4个字节)

*@paramindex

* 开始位置

*@return

*/

public static float toFloat(byte[] b) {intl;

l= b[0];

l&= 0xff;

l|= ((int) b[1] << 8);

l&= 0xffff;

l|= ((int) b[2] << 16);

l&= 0xffffff;

l|= ((int) b[3] << 24);returnFloat.intBitsToFloat(l);

}/*** 浮点转换为字节

*

*@paramf

*@return

*/

public static byte[] toByteArr(floatf) {//把float转换为byte[]

int fbit =Float.floatToIntBits(f);byte[] b = new byte[4];for (int i = 0; i < 4; i++) {

b[i]= (byte) (fbit >> (24 - i * 8));

}//翻转数组

int len =b.length;//建立一个与源数组元素类型相同的数组

byte[] dest = new byte[len];//为了防止修改源数组,将源数组拷贝一份副本

System.arraycopy(b, 0, dest, 0, len);bytetemp;//将顺位第i个与倒数第i个交换

for (int i = 0; i < len / 2; ++i) {

temp=dest[i];

dest[i]= dest[len - i - 1];

dest[len- i - 1] =temp;

}returndest;

}public static voidmain(String args[]) {

String path= "F:\\three.js-master\\examples\\models\\stl\\ascii\\pr2_head_pan.stl";//ascii

path = "F:\\three.js-master\\examples\\models\\stl\\binary\\pr2_head_pan.stl";//

//binary

path = "F:\\three.js-master\\examples\\models\\stl\\binary\\colored.stl";//

//binary-with-color//path = "D:\\用户目录\\下载\\4s-keychain-keychain-kickstand-hHkUg.stl";

if(STLUtils.isBinary(path)) {

System.out.println(true);

STLUtils.parseBinary(path);

}else{

STLUtils.parseASCII(path);

}

}

}

java stl分解_stl文件格式解析代码--java版相关推荐

  1. java stl分解_[STL训练]寻梦-题解(Java代码)极简思路

    注意事项:  insert()方法只能被 StringBuffer 类的对象调用 参考代码: import java.util.Scanner; public class Main { private ...

  2. java stl分解_Java Thread 之間 記憶體空間分析

    Java Thread 之間 記憶體空間分析 SimpleThread.java import com.abc.ChirpControllerDevice; public class SimpleTh ...

  3. java自带的xml解析,使用Java自带SAX工具解析XML

    studentInfo.xml 崔卫兵 PC学院 62354666 男,1982年生,硕士,现就读于北京邮电大学 cwb PC学院 62358888 男,1987年生,硕士,现就读于中国农业大学 xx ...

  4. java 装配模式_java23种设计模式代码 Java装配模式

    一 模板设计模式在多个子类中 , 存在一个共同的方法 , 这个方法拥有相同的执行步骤 . 为了提高代码的复用性 , 将这个相同步骤的方法抽象到父类中 , 形成模板方 法为了让子类能够控制父类中模板方. ...

  5. eclipse 停止java程序运行_Eclipse:停止运行代码(java)

    有时,我会运行一个偶然包含无限循环之类的程序. Eclipse让我继续编辑程序,但速度非常慢. 我该如何阻止它? (我是否想重新启动JVM?)重新启动eclipse本身总是可行的,但这会中断我的工作流 ...

  6. java连连看两个拐点消除代码,java连连看代码 图片模式,不要百度上那个

    图片模式,不要百度上那个数字的爱情就如一杯牛奶咖啡,香香地飘在外面,甜甜地浮在表面,酸酸地含在里面,苦苦地沉在底面,模模糊糊地把你倒映在咖啡里面. import javax.swing.*; impo ...

  7. java jsoup 网络爬虫 jsoup解析html Java爬虫 Jsoup爬虫 jsoup例子

    java jsoup 网络爬虫 java jsoup 网络爬虫 学习例子(一)抓取豆瓣电影名称+推荐星级 java jsoup 网络爬虫 学习例子(二)只抓取豆瓣电影5星(力荐)电影名称 java j ...

  8. java 以管理员执行cmd_cmd管理员代码 JAVA 管理员权限运行CMD文件

    敲什么命令可以以管理员身份启动cmd 我建了一个.bat文件,想启动mysql服务,但是必须是以管理员身份去启动才代码如下: @echo off>nul 2>&1 "%S ...

  9. java 解析日期格式_日期/时间格式/解析,Java 8样式

    java 解析日期格式 自Java 几乎 开始以来,Java开发人员就通过java.util.Date类(自JDK 1.0起)和java.util.Calendar类(自JDK 1.1起 )来处理日期 ...

  10. 日期/时间格式/解析,Java 8样式

    自Java 几乎 开始以来,Java开发人员就通过java.util.Date类(自JDK 1.0起)和java.util.Calendar类(自JDK 1.1起 )来处理日期和时间. 在这段时间内, ...

最新文章

  1. opengl glad.h和 glu.h
  2. AGC023D - Go Home
  3. 【华为云技术分享】开发团队中的任务没人领取,你头疼吗?
  4. SpringBoot集成gRPC微服务工程搭建实践
  5. Linux访问windows共享文件夹
  6. Why hash maps in Java 8 use binary tree instead of linked list?
  7. Directx游戏中嵌入IE浏览器实现过程
  8. 创意字体设计,创意思路哪里找
  9. Android10手机OTG按钮,我又来了-荣耀10青春版手机OTG功能你会用吗?
  10. (银行案例)智能营销赋能大零售转型
  11. 七成知识分子走在过劳死边缘
  12. 一剑走江湖---武汉
  13. 纺织企业举步维艰,小微纺织企业该如何做?
  14. matlab怎么多重积分,多重积分的MATLAB实现
  15. 有关likely和unlikely
  16. python如何赋值给元组_【Python 1-9】Python手把手教程之——元组和元组的使用技巧...
  17. 苹果id被锁定恢复方法(appleid被锁定怎么解除)
  18. 广州大学2020操作系统实验二:银行家算法
  19. 英语不好影响考PMP吗?
  20. zynq+ad9361 petalinux使用官方IIO示波器调试记录

热门文章

  1. 如何在云服务器上自动运行.py文件
  2. 吴裕雄--天生自然 高等数学学习:斯托克斯公式、环流量与旋度
  3. AudioRecord的用法
  4. Elasticsearch:Dissect 和 Grok 处理器之间的区别
  5. Elasticsearch:Elastic可观测性 - 运用 pipeline 使数据结构化
  6. nginx最简单的旧域名跳转新域名
  7. 字符乱码出现的原因及解决办法
  8. 基于Modelingtoolkit的管网组件(Julia)
  9. scrapy 爬取酷狗热门歌手音乐
  10. Codeforces_714_A