整理文件夹及架构,加入打印机页面,octo反代有问题

This commit is contained in:
2026-04-14 00:11:00 +08:00
parent 1de35f21d7
commit 570af7c225
54 changed files with 939 additions and 292 deletions

View File

@@ -0,0 +1,23 @@
# Third-Party Licenses
This project uses the following third-party libraries, bundled in the `assets` folder.
## Frontend Libraries
1. **Bootstrap v5.3** (CSS/JS)
- License: MIT
- Source: https://getbootstrap.com/
2. **Bootstrap Icons**
- License: MIT
- Source: https://icons.getbootstrap.com/
3. **Three.js** (including Extra Controls / Loaders)
- License: MIT
- Source: https://threejs.org/
4. **GCode Preview**
- License: MIT
- Source: https://github.com/remcoder/gcode-preview
These libraries and their copyright notices belong to their respective creators. See individual source files or official repos for exact license texts.

View File

@@ -0,0 +1,15 @@
Notice regarding the CSS styles and Fonts included in this directory:
This project as a whole is licensed under the GNU General Public License v3.0 (GPLv3).
However, the included CSS and Font dependencies are distributed under their own permissive licenses (which are fully compatible with GPLv3).
1. Bootstrap (bootstrap.min.css)
- Copyright (c) 2011-2023 The Bootstrap Authors
- Licensed under the MIT License
- https://github.com/twbs/bootstrap/blob/main/LICENSE
2. Bootstrap Icons (bootstrap-icons.css, fonts/bootstrap-icons.woff, etc.)
- Copyright (c) 2019-2023 The Bootstrap Authors
- Font files are licensed under the SIL Open Font License (OFL) v1.1.
- The CSS generated code is licensed under the MIT License.
- https://github.com/twbs/icons/blob/main/LICENSE

1981
app/assets/css/bootstrap-icons.css vendored Normal file

File diff suppressed because it is too large Load Diff

6
app/assets/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

117
app/assets/i18n/en.json Normal file
View File

@@ -0,0 +1,117 @@
{
"Language": "Language",
"English": "English",
"Chinese": "中文",
"Guest": "Guest",
"Login": "Login",
"Logout": "Logout",
"Home": "Home",
"New Slice": "New Slice",
"My Files": "My Files",
"Admin Options": "Admin Options",
"System Settings": "System Settings",
"User Management": "User Management",
"Dashboard": "Dashboard",
"Total Prints": "Total Prints",
"You have sliced": "You have sliced",
"files": "files.",
"Upload & Slice STL": "Upload & Slice STL",
"Select STL File": "Select STL File",
"Quality Profile": "Quality Profile",
"Upload & Slice": "Upload & Slice",
"3D Preview Area": "3D Preview Area",
"Upload a file to display": "Upload a file to display",
"Date Uploaded": "Date Uploaded",
"Original Name": "Original Name",
"Status": "Status",
"Actions": "Actions",
"Uploaded": "Uploaded",
"Waiting": "Waiting",
"Other Settings": "Other Settings",
"Infill Density": "Infill Density",
"Support": "Support",
"None": "None",
"Touching Buildplate": "Touching Buildplate",
"Everywhere": "Everywhere",
"Merging": "Merging",
"Waiting in queue for slicing": "Waiting in queue for slicing",
"Slicing": "Slicing",
"Sliced": "Sliced",
"Failed": "Failed",
"Download GCode": "Download GCode",
"GCode Preview": "GCode Preview",
"Delete": "Delete",
"No files uploaded yet.": "No files uploaded yet.",
"Drag & Drop STL files here or Click to Select": "Drag & Drop STL files here or Click to Select",
"Uploading...": "Uploading...",
"Simplifying": "Simplifying",
"Simplifying...": "Simplifying...",
"Proxy Skip Size (MB)": "Proxy Skip Size (MB)",
"Files smaller than this will not generate a simplified proxy.": "Files smaller than this will not generate a simplified proxy.",
"Slicing queued!": "Slicing queued!",
"Draft Quality": "Draft Quality",
"Standard Quality": "Standard Quality",
"High Quality": "High Quality",
"Dynamic Quality": "Dynamic Quality",
"Low Quality": "Low Quality",
"Super Quality": "Super Quality",
"Ultra Quality": "Ultra Quality",
"Plater": "Plater",
"Layer Progress:": "Layer Progress:",
"Loading and Parsing GCode Data...": "Loading and Parsing GCode Data...",
"Failed to load GCode preview.": "Failed to load GCode preview.",
"Outer Wall": "Outer Wall",
"Inner Wall": "Inner Wall",
"Infill": "Infill",
"Skin/TopBottom": "Skin/TopBottom",
"Travel (Move)": "Travel (Move)",
"Skirt": "Skirt",
"Support Interface": "Support Interface",
"Back": "Back",
"Layer": "Layer",
"Plater / Build Plate": "Plater / Build Plate",
"Translate (W)": "Translate (W)",
"Rotate (E)": "Rotate (E)",
"Scale (R)": "Scale (R)",
"Scale": "Scale",
"Uniform Scale": "Uniform Scale",
"Lay Flat": "Lay Flat",
"Remove Selected (Del)": "Remove Selected (Del)",
"Available Models": "Available Models",
"No STL models uploaded yet. Go upload some first.": "No STL models uploaded yet. Go upload some first.",
"Support Type": "Support Type",
"Tree": "Tree",
"Lines": "Lines",
"Grid": "Grid",
"Triangles": "Triangles",
"Concentric": "Concentric",
"Zig Zag": "Zig Zag",
"Cross": "Cross",
"Gyroid": "Gyroid",
"Honeycomb": "Honeycomb",
"Octagon": "Octagon",
"Clear Board": "Clear Board",
"Merge & Slice": "Merge & Slice",
"Error loading STL model file.": "Error loading STL model file.",
"Please add at least one model to the build plate.": "Please add at least one model to the build plate.",
"One or more models are outside the print area. Please adjust them before slicing.": "One or more models are outside the print area. Please adjust them before slicing.",
"Error:": "Error:",
"ID": "ID",
"Username": "Username",
"Role": "Role",
"Created At": "Created At",
"Admin": "Admin",
"User": "User",
"WARNING: Are you sure you want to permanently delete this user AND ALL their uploaded files and G-codes?": "WARNING: Are you sure you want to permanently delete this user AND ALL their uploaded files and G-codes?",
"CuraEngine Configurations": "CuraEngine Configurations",
"Plater Origin Offset X (mm)": "Plater Origin Offset X (mm)",
"Adjust the X-axis compilation offset for combined files on the build plate.": "Adjust the X-axis compilation offset for combined files on the build plate.",
"Plater Origin Offset Y (mm)": "Plater Origin Offset Y (mm)",
"Adjust the Y-axis compilation offset for combined files on the build plate.": "Adjust the Y-axis compilation offset for combined files on the build plate.",
"Default Plater Settings": "Default Plater Settings",
"Default Infill Density (%)": "Default Infill Density (%)",
"Default Support": "Default Support",
"Default Support Type": "Default Support Type",
"Default Quality Profile": "Default Quality Profile",
"Save Settings": "Save Settings"
}

123
app/assets/i18n/zh-cn.json Normal file
View File

@@ -0,0 +1,123 @@
{
"Language": "语言",
"English": "English",
"Chinese": "中文",
"Guest": "访客",
"Login": "登录",
"Logout": "退出",
"Home": "主页",
"New Slice": "新建切片",
"My Files": "我的文件",
"Admin Options": "管理员选项",
"System Settings": "系统设置",
"User Management": "用户管理",
"Dashboard": "仪表盘",
"Total Prints": "总打印数",
"You have sliced": "您已切片",
"files": "个文件。",
"Upload & Slice STL": "上传并切片 STL",
"Select STL File": "选择 STL 文件",
"Quality Profile": "质量配置",
"Upload & Slice": "上传 & 切片",
"3D Preview Area": "3D预览区",
"Upload a file to display": "上传文件以显示",
"Date Uploaded": "上传日期",
"Original Name": "原始名称",
"Status": "状态",
"Actions": "操作",
"Waiting": "等待中",
"Merging": "合并中",
"Waiting in queue for slicing": "在队列中排队等待切片",
"Slicing": "切片中",
"Sliced": "已切片",
"Uploaded": "已上传",
"Failed": "失败",
"This model has already been sliced. The existing GCode will be overwritten. Continue?": "该模型已经生成过切片重新切片会覆盖原有GCode文件是否继续",
"Upload STL": "上传STL",
"Download GCode": "下载 GCode",
"GCode Preview": "GCode 预览",
"Delete": "删除",
"No files uploaded yet.": "还没有上传文件。",
"Drag & Drop STL files here or Click to Select": "将 STL 文件拖放到此处或点击选择",
"Uploading...": "上传中...",
"Simplifying": "简化中",
"Simplifying...": "正在简化...",
"Proxy Skip Size (MB)": "代理免简化大小 (MB)",
"Files smaller than this will not generate a simplified proxy.": "极小体积的文件无需降维生成加速展现的代理文件。",
"Upload Complete!": "上传完成!",
"Upload error.": "上传出错。",
"Upload failed.": "上传失败。",
"Please upload a valid .stl file!": "请上传有效的 .stl 文件!",
"Slicing queued!": "切片已排队!",
"Draft Quality": "草稿质量",
"Standard Quality": "标准质量",
"High Quality": "高质量",
"Dynamic Quality": "动态质量",
"Low Quality": "低质量",
"Super Quality": "超高质量",
"Ultra Quality": "极高质量",
"Plater": "构建板",
"Layer Progress:": "单层打印进度:",
"Loading and Parsing GCode Data...": "正在加载和解析 GCode 数据...",
"Failed to load GCode preview.": "加载 GCode 预览失败。",
"Outer Wall": "外墙",
"Inner Wall": "内墙",
"Infill": "填充",
"Skin/TopBottom": "顶层/底层",
"Travel (Move)": "空驶",
"Skirt": " 裙边",
"Support Interface": "支撑界面",
"Back": "返回",
"Layer": "层数",
"Plater / Build Plate": "构建板",
"Translate (W)": "平移 (W)",
"Rotate (E)": "旋转 (E)",
"Scale (R)": "缩放 (R)",
"Scale": "缩放",
"Uniform Scale": "均匀缩放",
"Lay Flat": "平放",
"Remove Selected (Del)": "删除选中 (Del)",
"Available Models": "可用模型",
"No STL models uploaded yet. Go upload some first.": "还没有上传 STL 模型。请先上传。",
"Other Settings": "其它设置",
"Infill Density": "填充密度",
"Support": "支撑",
"None": "无",
"Touching Buildplate": "仅接触构建板",
"Everywhere": "无处不在",
"Support Type": "支撑类型",
"Tree": "树状",
"Lines": "直线",
"Grid": "网格",
"Triangles": "三角形",
"Concentric": "同心",
"Zig Zag": "之字形",
"Cross": "交叉",
"Gyroid": "螺旋",
"Honeycomb": "蜂窝",
"Octagon": "八边形",
"Clear Board": "清空画板",
"Merge & Slice": "合并并切片",
"Error loading STL model file.": "加载 STL 模型文件出错。",
"Please add at least one model to the build plate.": "请在构建板上至少放置一个模型。",
"One or more models are outside the print area. Please adjust them before slicing.": "有一个或多个模型超出了打印范围。切片前请调整它们的位置。",
"Error:": "错误:",
"ID": "ID",
"Username": "用户名",
"Role": "角色",
"Created At": "创建时间",
"Admin": "管理员",
"User": "普通用户",
"WARNING: Are you sure you want to permanently delete this user AND ALL their uploaded files and G-codes?": "警告确定要永久删除该用户以及TA上传的所有文件和切片吗",
"CuraEngine Configurations": "CuraEngine 配置",
"Plater Origin Offset X (mm)": "构建板原点偏移 X (mm)",
"Adjust the X-axis compilation offset for combined files on the build plate.": "调整多文件在构建板合并切片时的X坐标偏移。",
"Plater Origin Offset Y (mm)": "构建板原点偏移 Y (mm)",
"Adjust the Y-axis compilation offset for combined files on the build plate.": "调整多文件在构建板合并切片时的Y坐标偏移。",
"Default Plater Settings": "默认构建板设置",
"Default Infill Density (%)": "默认填充密度 (%)",
"Default Support": "默认支撑类型",
"Default Support Type": "默认支撑图案",
"Default Quality Profile": "默认质量配置",
"Save Settings": "保存设置"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
Notice regarding the JavaScript libraries included in this directory:
This project as a whole is licensed under the GNU General Public License v3.0 (GPLv3).
However, the included JavaScript dependencies are distributed under their own permissive licenses (which are fully compatible with GPLv3).
1. Bootstrap (bootstrap.bundle.min.js)
- Copyright (c) 2011-2023 The Bootstrap Authors
- Licensed under the MIT License
- https://github.com/twbs/bootstrap/blob/main/LICENSE
2. Three.js (three.min.js, OrbitControls.js, STLLoader.js)
- Copyright © 2010-2023 three.js authors
- Licensed under the MIT License
- https://github.com/mrdoob/three.js/blob/dev/LICENSE

371
app/assets/js/STLLoader.js Normal file
View File

@@ -0,0 +1,371 @@
( function () {
/**
* Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.
*
* Supports both binary and ASCII encoded files, with automatic detection of type.
*
* The loader returns a non-indexed buffer geometry.
*
* Limitations:
* Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
* There is perhaps some question as to how valid it is to always assume little-endian-ness.
* ASCII decoding assumes file is UTF-8.
*
* Usage:
* const loader = new STLLoader();
* loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {
* scene.add( new THREE.Mesh( geometry ) );
* });
*
* For binary STLs geometry might contain colors for vertices. To use it:
* // use the same code to load STL as above
* if (geometry.hasColors) {
* material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true });
* } else { .... }
* const mesh = new THREE.Mesh( geometry, material );
*
* For ASCII STLs containing multiple solids, each solid is assigned to a different group.
* Groups can be used to assign a different color by defining an array of materials with the same length of
* geometry.groups and passing it to the Mesh constructor:
*
* const mesh = new THREE.Mesh( geometry, material );
*
* For example:
*
* const materials = [];
* const nGeometryGroups = geometry.groups.length;
*
* const colorMap = ...; // Some logic to index colors.
*
* for (let i = 0; i < nGeometryGroups; i++) {
*
* const material = new THREE.MeshPhongMaterial({
* color: colorMap[i],
* wireframe: false
* });
*
* }
*
* materials.push(material);
* const mesh = new THREE.Mesh(geometry, materials);
*/
class STLLoader extends THREE.Loader {
constructor( manager ) {
super( manager );
}
load( url, onLoad, onProgress, onError ) {
const scope = this;
const loader = new THREE.FileLoader( this.manager );
loader.setPath( this.path );
loader.setResponseType( 'arraybuffer' );
loader.setRequestHeader( this.requestHeader );
loader.setWithCredentials( this.withCredentials );
loader.load( url, function ( text ) {
try {
onLoad( scope.parse( text ) );
} catch ( e ) {
if ( onError ) {
onError( e );
} else {
console.error( e );
}
scope.manager.itemError( url );
}
}, onProgress, onError );
}
parse( data ) {
function isBinary( data ) {
const reader = new DataView( data );
const face_size = 32 / 8 * 3 + 32 / 8 * 3 * 3 + 16 / 8;
const n_faces = reader.getUint32( 80, true );
const expect = 80 + 32 / 8 + n_faces * face_size;
if ( expect === reader.byteLength ) {
return true;
} // An ASCII STL data must begin with 'solid ' as the first six bytes.
// However, ASCII STLs lacking the SPACE after the 'd' are known to be
// plentiful. So, check the first 5 bytes for 'solid'.
// Several encodings, such as UTF-8, precede the text with up to 5 bytes:
// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
// Search for "solid" to start anywhere after those prefixes.
// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
const solid = [ 115, 111, 108, 105, 100 ];
for ( let off = 0; off < 5; off ++ ) {
// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
if ( matchDataViewAt( solid, reader, off ) ) return false;
} // Couldn't find "solid" text at the beginning; it is binary STL.
return true;
}
function matchDataViewAt( query, reader, offset ) {
// Check if each byte in query matches the corresponding byte from the current offset
for ( let i = 0, il = query.length; i < il; i ++ ) {
if ( query[ i ] !== reader.getUint8( offset + i, false ) ) return false;
}
return true;
}
function parseBinary( data ) {
const reader = new DataView( data );
const faces = reader.getUint32( 80, true );
let r,
g,
b,
hasColors = false,
colors;
let defaultR, defaultG, defaultB, alpha; // process STL header
// check for default color in header ("COLOR=rgba" sequence).
for ( let index = 0; index < 80 - 10; index ++ ) {
if ( reader.getUint32( index, false ) == 0x434F4C4F
/*COLO*/
&& reader.getUint8( index + 4 ) == 0x52
/*'R'*/
&& reader.getUint8( index + 5 ) == 0x3D
/*'='*/
) {
hasColors = true;
colors = new Float32Array( faces * 3 * 3 );
defaultR = reader.getUint8( index + 6 ) / 255;
defaultG = reader.getUint8( index + 7 ) / 255;
defaultB = reader.getUint8( index + 8 ) / 255;
alpha = reader.getUint8( index + 9 ) / 255;
}
}
const dataOffset = 84;
const faceLength = 12 * 4 + 2;
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array( faces * 3 * 3 );
const normals = new Float32Array( faces * 3 * 3 );
for ( let face = 0; face < faces; face ++ ) {
const start = dataOffset + face * faceLength;
const normalX = reader.getFloat32( start, true );
const normalY = reader.getFloat32( start + 4, true );
const normalZ = reader.getFloat32( start + 8, true );
if ( hasColors ) {
const packedColor = reader.getUint16( start + 48, true );
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;
}
}
for ( let i = 1; i <= 3; i ++ ) {
const vertexstart = start + i * 12;
const componentIdx = face * 3 * 3 + ( i - 1 ) * 3;
vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
normals[ componentIdx ] = normalX;
normals[ componentIdx + 1 ] = normalY;
normals[ componentIdx + 2 ] = normalZ;
if ( hasColors ) {
colors[ componentIdx ] = r;
colors[ componentIdx + 1 ] = g;
colors[ componentIdx + 2 ] = b;
}
}
}
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
if ( hasColors ) {
geometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.hasColors = true;
geometry.alpha = alpha;
}
return geometry;
}
function parseASCII( data ) {
const geometry = new THREE.BufferGeometry();
const patternSolid = /solid([\s\S]*?)endsolid/g;
const patternFace = /facet([\s\S]*?)endfacet/g;
let faceCounter = 0;
const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source;
const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' );
const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' );
const vertices = [];
const normals = [];
const normal = new THREE.Vector3();
let result;
let groupCount = 0;
let startVertex = 0;
let endVertex = 0;
while ( ( result = patternSolid.exec( data ) ) !== null ) {
startVertex = endVertex;
const solid = result[ 0 ];
while ( ( result = patternFace.exec( solid ) ) !== null ) {
let vertexCountPerFace = 0;
let normalCountPerFace = 0;
const text = result[ 0 ];
while ( ( result = patternNormal.exec( text ) ) !== null ) {
normal.x = parseFloat( result[ 1 ] );
normal.y = parseFloat( result[ 2 ] );
normal.z = parseFloat( result[ 3 ] );
normalCountPerFace ++;
}
while ( ( result = patternVertex.exec( text ) ) !== null ) {
vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
normals.push( normal.x, normal.y, normal.z );
vertexCountPerFace ++;
endVertex ++;
} // every face have to own ONE valid normal
if ( normalCountPerFace !== 1 ) {
console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
} // each face have to own THREE valid vertices
if ( vertexCountPerFace !== 3 ) {
console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
}
faceCounter ++;
}
const start = startVertex;
const count = endVertex - startVertex;
geometry.addGroup( start, count, groupCount );
groupCount ++;
}
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
return geometry;
}
function ensureString( buffer ) {
if ( typeof buffer !== 'string' ) {
return THREE.LoaderUtils.decodeText( new Uint8Array( buffer ) );
}
return buffer;
}
function ensureBinary( buffer ) {
if ( typeof buffer === 'string' ) {
const array_buffer = new Uint8Array( buffer.length );
for ( let i = 0; i < buffer.length; i ++ ) {
array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
}
return array_buffer.buffer || array_buffer;
} else {
return buffer;
}
} // start
const binData = ensureBinary( data );
return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) );
}
}
THREE.STLLoader = STLLoader;
} )();

View File

@@ -0,0 +1,371 @@
( function () {
/**
* Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.
*
* Supports both binary and ASCII encoded files, with automatic detection of type.
*
* The loader returns a non-indexed buffer geometry.
*
* Limitations:
* Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
* There is perhaps some question as to how valid it is to always assume little-endian-ness.
* ASCII decoding assumes file is UTF-8.
*
* Usage:
* const loader = new STLLoader();
* loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {
* scene.add( new THREE.Mesh( geometry ) );
* });
*
* For binary STLs geometry might contain colors for vertices. To use it:
* // use the same code to load STL as above
* if (geometry.hasColors) {
* material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true });
* } else { .... }
* const mesh = new THREE.Mesh( geometry, material );
*
* For ASCII STLs containing multiple solids, each solid is assigned to a different group.
* Groups can be used to assign a different color by defining an array of materials with the same length of
* geometry.groups and passing it to the Mesh constructor:
*
* const mesh = new THREE.Mesh( geometry, material );
*
* For example:
*
* const materials = [];
* const nGeometryGroups = geometry.groups.length;
*
* const colorMap = ...; // Some logic to index colors.
*
* for (let i = 0; i < nGeometryGroups; i++) {
*
* const material = new THREE.MeshPhongMaterial({
* color: colorMap[i],
* wireframe: false
* });
*
* }
*
* materials.push(material);
* const mesh = new THREE.Mesh(geometry, materials);
*/
class STLLoader extends THREE.Loader {
constructor( manager ) {
super( manager );
}
load( url, onLoad, onProgress, onError ) {
const scope = this;
const loader = new THREE.FileLoader( this.manager );
loader.setPath( this.path );
loader.setResponseType( 'arraybuffer' );
loader.setRequestHeader( this.requestHeader );
loader.setWithCredentials( this.withCredentials );
loader.load( url, function ( text ) {
try {
onLoad( scope.parse( text ) );
} catch ( e ) {
if ( onError ) {
onError( e );
} else {
console.error( e );
}
scope.manager.itemError( url );
}
}, onProgress, onError );
}
parse( data ) {
function isBinary( data ) {
const reader = new DataView( data );
const face_size = 32 / 8 * 3 + 32 / 8 * 3 * 3 + 16 / 8;
const n_faces = reader.getUint32( 80, true );
const expect = 80 + 32 / 8 + n_faces * face_size;
if ( expect === reader.byteLength ) {
return true;
} // An ASCII STL data must begin with 'solid ' as the first six bytes.
// However, ASCII STLs lacking the SPACE after the 'd' are known to be
// plentiful. So, check the first 5 bytes for 'solid'.
// Several encodings, such as UTF-8, precede the text with up to 5 bytes:
// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
// Search for "solid" to start anywhere after those prefixes.
// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
const solid = [ 115, 111, 108, 105, 100 ];
for ( let off = 0; off < 5; off ++ ) {
// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
if ( matchDataViewAt( solid, reader, off ) ) return false;
} // Couldn't find "solid" text at the beginning; it is binary STL.
return true;
}
function matchDataViewAt( query, reader, offset ) {
// Check if each byte in query matches the corresponding byte from the current offset
for ( let i = 0, il = query.length; i < il; i ++ ) {
if ( query[ i ] !== reader.getUint8( offset + i, false ) ) return false;
}
return true;
}
function parseBinary( data ) {
const reader = new DataView( data );
const faces = reader.getUint32( 80, true );
let r,
g,
b,
hasColors = false,
colors;
let defaultR, defaultG, defaultB, alpha; // process STL header
// check for default color in header ("COLOR=rgba" sequence).
for ( let index = 0; index < 80 - 10; index ++ ) {
if ( reader.getUint32( index, false ) == 0x434F4C4F
/*COLO*/
&& reader.getUint8( index + 4 ) == 0x52
/*'R'*/
&& reader.getUint8( index + 5 ) == 0x3D
/*'='*/
) {
hasColors = true;
colors = new Float32Array( faces * 3 * 3 );
defaultR = reader.getUint8( index + 6 ) / 255;
defaultG = reader.getUint8( index + 7 ) / 255;
defaultB = reader.getUint8( index + 8 ) / 255;
alpha = reader.getUint8( index + 9 ) / 255;
}
}
const dataOffset = 84;
const faceLength = 12 * 4 + 2;
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array( faces * 3 * 3 );
const normals = new Float32Array( faces * 3 * 3 );
for ( let face = 0; face < faces; face ++ ) {
const start = dataOffset + face * faceLength;
const normalX = reader.getFloat32( start, true );
const normalY = reader.getFloat32( start + 4, true );
const normalZ = reader.getFloat32( start + 8, true );
if ( hasColors ) {
const packedColor = reader.getUint16( start + 48, true );
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;
}
}
for ( let i = 1; i <= 3; i ++ ) {
const vertexstart = start + i * 12;
const componentIdx = face * 3 * 3 + ( i - 1 ) * 3;
vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
normals[ componentIdx ] = normalX;
normals[ componentIdx + 1 ] = normalY;
normals[ componentIdx + 2 ] = normalZ;
if ( hasColors ) {
colors[ componentIdx ] = r;
colors[ componentIdx + 1 ] = g;
colors[ componentIdx + 2 ] = b;
}
}
}
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
if ( hasColors ) {
geometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.hasColors = true;
geometry.alpha = alpha;
}
return geometry;
}
function parseASCII( data ) {
const geometry = new THREE.BufferGeometry();
const patternSolid = /solid([\s\S]*?)endsolid/g;
const patternFace = /facet([\s\S]*?)endfacet/g;
let faceCounter = 0;
const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source;
const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' );
const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' );
const vertices = [];
const normals = [];
const normal = new THREE.Vector3();
let result;
let groupCount = 0;
let startVertex = 0;
let endVertex = 0;
while ( ( result = patternSolid.exec( data ) ) !== null ) {
startVertex = endVertex;
const solid = result[ 0 ];
while ( ( result = patternFace.exec( solid ) ) !== null ) {
let vertexCountPerFace = 0;
let normalCountPerFace = 0;
const text = result[ 0 ];
while ( ( result = patternNormal.exec( text ) ) !== null ) {
normal.x = parseFloat( result[ 1 ] );
normal.y = parseFloat( result[ 2 ] );
normal.z = parseFloat( result[ 3 ] );
normalCountPerFace ++;
}
while ( ( result = patternVertex.exec( text ) ) !== null ) {
vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
normals.push( normal.x, normal.y, normal.z );
vertexCountPerFace ++;
endVertex ++;
} // every face have to own ONE valid normal
if ( normalCountPerFace !== 1 ) {
console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
} // each face have to own THREE valid vertices
if ( vertexCountPerFace !== 3 ) {
console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
}
faceCounter ++;
}
const start = startVertex;
const count = endVertex - startVertex;
geometry.addGroup( start, count, groupCount );
groupCount ++;
}
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
return geometry;
}
function ensureString( buffer ) {
if ( typeof buffer !== 'string' ) {
return THREE.LoaderUtils.decodeText( new Uint8Array( buffer ) );
}
return buffer;
}
function ensureBinary( buffer ) {
if ( typeof buffer === 'string' ) {
const array_buffer = new Uint8Array( buffer.length );
for ( let i = 0; i < buffer.length; i ++ ) {
array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
}
return array_buffer.buffer || array_buffer;
} else {
return buffer;
}
} // start
const binData = ensureBinary( data );
return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) );
}
}
THREE.STLLoader = STLLoader;
} )();

File diff suppressed because it is too large Load Diff

7
app/assets/js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
app/assets/js/gcode-preview.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
app/assets/js/three.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long