修复偏移问题,修复代理问题

This commit is contained in:
2026-04-15 00:22:12 +08:00
parent 570af7c225
commit f0f9d658eb
33 changed files with 1621 additions and 1763 deletions

222
app/assets/i18n/de.json Normal file
View File

@@ -0,0 +1,222 @@
{
"Language": "Sprache",
"English": "English",
"Chinese": "中文",
"Guest": "Gast",
"Login": "Anmelden",
"Logout": "Abmelden",
"Home": "Startseite",
"New Slice": "Neuer Slice",
"My Files": "Meine Dateien",
"Admin Options": "Admin-Optionen",
"System Settings": "Systemeinstellungen",
"User Management": "Benutzerverwaltung",
"Dashboard": "Dashboard",
"Total Prints": "Gesamte Drucke",
"You have sliced": "Sie haben",
"files": "Dateien gesliced.",
"Upload & Slice STL": "STL Hochladen & Slicen",
"Select STL File": "STL-Datei auswählen",
"Quality Profile": "Qualitätsprofil",
"Upload & Slice": "Hochladen & Slicen",
"3D Preview Area": "3D-Vorschaubereich",
"Upload a file to display": "Eine Datei zur Anzeige hochladen",
"Date Uploaded": "Hochladedatum",
"Original Name": "Originalname",
"Status": "Status",
"Actions": "Aktionen",
"Waiting": "Wartend",
"Merging": "Zusammenführen",
"Waiting in queue for slicing": "Wartet in der Warteschlange aufs Slicen",
"Slicing": "Slicen",
"Sliced": "Gesliced",
"Uploaded": "Hochgeladen",
"Failed": "Fehlgeschlagen",
"This model has already been sliced. The existing GCode will be overwritten. Continue?": "Dieses Modell wurde bereits gesliced. Der existierende GCode wird überschrieben. Fortfahren?",
"Upload STL": "STL hochladen",
"Download GCode": "GCode Herunterladen",
"GCode Preview": "GCode Vorschau",
"Delete": "Löschen",
"No files uploaded yet.": "Noch keine Dateien hochgeladen.",
"Drag & Drop STL files here or Click to Select": "STL-Dateien hierher ziehen & ablegen oder zum Auswählen klicken",
"Uploading...": "Lädt hoch...",
"Simplifying": "Vereinfache",
"Simplifying...": "Vereinfache...",
"Proxy Skip Size (MB)": "Proxy-Überspringgröße (MB)",
"Files smaller than this will not generate a simplified proxy.": "Dateien, die kleiner sind, werden keine vereinfachte Proxy generieren.",
"Upload Complete!": "Hochladen abgeschlossen!",
"Upload error.": "Fehler beim Hochladen.",
"Upload failed.": "Hochladen fehlgeschlagen.",
"Please upload a valid .stl file!": "Bitte laden Sie eine gültige .stl Datei hoch!",
"Slicing queued!": "Slicen in die Warteschlange eingereiht!",
"Draft Quality": "Entwurfsqualität",
"Standard Quality": "Standardqualität",
"High Quality": "Hohe Qualität",
"Dynamic Quality": "Dynamische Qualität",
"Low Quality": "Niedrige Qualität",
"Super Quality": "Super Qualität",
"Ultra Quality": "Ultra Qualität",
"Plater": "Druckplatte",
"Layer Progress:": "Schichtfortschritt:",
"Loading and Parsing GCode Data...": "Lade und verarbeite GCode-Daten...",
"Failed to load GCode preview.": "Fehler beim Laden der GCode-Vorschau.",
"Outer Wall": "Außenwand",
"Inner Wall": "Innenwand",
"Infill": "Füllung",
"Skin/TopBottom": "Hülle/ObenUnten",
"Travel (Move)": "Bewegung (Reise)",
"Skirt": "Skirt",
"Support Interface": "Stützstruktur-Grenzschicht",
"Back": "Zurück",
"Layer": "Schicht",
"Plater / Build Plate": "Druckbettleiste",
"Translate (W)": "Verschieben (W)",
"Rotate (E)": "Drehen (E)",
"Scale (R)": "Skalieren (R)",
"Scale": "Skalieren",
"Uniform Scale": "Gleichmäßige Skalierung",
"Lay Flat": "Flach legen",
"Remove Selected (Del)": "Ausgewähltes entfernen (Del)",
"Available Models": "Verfügbare Modelle",
"No STL models uploaded yet. Go upload some first.": "Noch keine STL-Modelle hochgeladen. Laden Sie zuerst einige hoch.",
"Other Settings": "Andere Einstellungen",
"Infill Density": "Fülldichte",
"Support": "Stützstruktur",
"None": "Keine",
"Touching Buildplate": "Nur Druckbett berührend",
"Everywhere": "Überall",
"Support Type": "Stützstruktur-Typ",
"Tree": "Baum",
"Lines": "Linien",
"Grid": "Gitter",
"Triangles": "Dreiecke",
"Concentric": "Konzentrisch",
"Zig Zag": "Zickzack",
"Cross": "Kreuz",
"Gyroid": "Gyroid",
"Honeycomb": "Wabe",
"Octagon": "Achteck",
"Clear Board": "Druckbett leeren",
"Merge & Slice": "Zusammenführen & Slicen",
"Error loading STL model file.": "Fehler beim Laden der STL-Datei.",
"Please add at least one model to the build plate.": "Bitte fügen Sie mindestens ein Modell zur Druckplatte hinzu.",
"One or more models are outside the print area. Please adjust them before slicing.": "Mindestens ein Modell liegt außerhalb des Druckbereichs. Bitte anpassen.",
"Error:": "Fehler:",
"ID": "ID",
"Username": "Benutzername",
"Role": "Rolle",
"Created At": "Erstellt am",
"Admin": "Admin",
"User": "Benutzer",
"WARNING: Are you sure you want to permanently delete this user AND ALL their uploaded files and G-codes?": "WARNUNG: Sind Sie sicher, dass Sie diesen Benutzer UND ALLE seine Dateien löschen wollen?",
"CuraEngine Configurations": "CuraEngine-Konfigurationen",
"Plater Origin Offset X (mm)": "Druckbett Ursprung Offset X (mm)",
"Adjust the X-axis compilation offset for combined files on the build plate.": "X-Achsen-Offset für kombinierte Dateien anpassen.",
"Plater Origin Offset Y (mm)": "Druckbett Ursprung Offset Y (mm)",
"Adjust the Y-axis compilation offset for combined files on the build plate.": "Y-Achsen-Offset für kombinierte Dateien anpassen.",
"Default Plater Settings": "Standard-Druckbetteinstellungen",
"Default Infill Density (%)": "Standard-Fülldichte (%)",
"Default Support": "Standard-Stützstruktur",
"Default Support Type": "Standard-Stützstruktur-Typ",
"Default Quality Profile": "Standard-Qualitätsprofil",
"Save Settings": "Einstellungen speichern",
"You are editing a composite model. The existing composite will be updated and re-sliced. Continue?": "Sie bearbeiten ein kombiniiges Modell. Fortfahren?",
"Select": "Auswählen",
"OctoPrint settings updated": "OctoPrint-Einstellungen aktualisiert",
"Settings updated successfully": "Einstellungen erfolgreich aktualisiert",
"Print starting! Going to dashboard...": "Druck startet! Gehe zum Dashboard...",
"Are you sure you want to delete this file?": "Sind Sie sicher, dass Sie diese Datei löschen wollen?",
"OctoPrint Base URL": "OctoPrint Basis-URL",
"Temperatures": "Temperaturen",
"Notice": "Hinweis",
"Please upload valid .stl files!": "Bitte gültige .stl hochladen!",
"Print Time:": "Druckzeit:",
"System Configuration": "Systemkonfiguration",
"Command": "Befehl",
"Time Left:": "Verbleibende Zeit:",
"Yes": "Ja",
"Current State": "Aktueller Zustand",
"Error updating settings": "Fehler beim Aktualisieren der Einstellungen",
"Available Files on Printer": "Verfügbare Dateien auf dem Drucker",
"Control failed: ": "Steuerung fehlgeschlagen: ",
"Loading webcam stream...": "Lade Webcam-Stream...",
"Live Webcam": "Live-Webcam",
"No printable files found. Go slice some G-Code first!": "Keine druckbaren Dateien gefunden. Erst G-Code slicen!",
"Save Connection Settings": "Verbindungseinstellungen speichern",
"Validation Failed": "Validierung fehlgeschlagen",
"Cancel Print": "Drucken abbrechen",
"Send this file to print immediately?": "Diese Datei sofort zum Druck senden?",
"Print Now": "Jetzt drucken",
"OctoPrint Panel (Embedded)": "OctoPrint-Panel (Eingebettet)",
"Are you sure you want to perform this action?": "Sind Sie sicher, dass Sie die Aktion ausführen wollen?",
"Control": "Steuerung",
"Cancel": "Abbrechen",
"sent.": "gesendet.",
"The local IP address or hostname of your OctoPrint server.": "Lokale IP-Adresse oder Hostname Ihres OctoPrint-Servers.",
"OctoPrint Panel": "OctoPrint-Panel",
"General Operations": "Allgemeine Operationen",
"Confirm": "Bestätigen",
"Basic Control": "Basiskontrolle",
"Size:": "Größe:",
"Prepare Print": "Druck vorbereiten",
"API Key / Application Key": "API-Schlüssel / Anwendungsschlüssel",
"Configuration Required:": "Konfiguration erforderlich:",
"Paste API Key here": "API-Schlüssel hier einfügen",
"Tool/Nozzle": "Werkzeug/Düse",
"Pause/Resume": "Pause/Fortsetzen",
"Can be found in OctoPrint Settings -> Application Keys or API.": "Befindet sich in den OctoPrint-Einstellungen -> Anwendungsschlüssel oder API.",
"Preview": "Vorschau",
"Pause": "Pause",
"Bed": "Druckbett",
"Printer Status": "Druckerstatus",
"Printer": "Drucker",
"Admin / OctoPrint": "Admin / OctoPrint",
"Absolute path to save locally sliced GCode files (e.g. OctoPrint uploads folder like \"/home/pi/.octoprint/uploads\"). Leave empty to use system default.": "Absoluter Pfad zum Speichern von GCode. Leer lassen für Systemstandard.",
"Custom GCode Output Folder": "Benutzerdefinierter GCode-Ausgabeordner",
"Go to Configuration": "Zur Konfiguration springen",
"OK": "OK",
"Connection Settings": "Verbindungseinstellungen",
"OctoPrint Configuration": "OctoPrint-Konfiguration",
"The OctoPrint URL is not set. Please go to the ": "Die OctoPrint-URL ist nicht gesetzt. Gehen Sie zu ",
"Go to Print": "Zum Druck",
"Time:": "Zeit:",
"Are you sure you want to cancel the print?": "Wollen Sie den Druck wirklich abbrechen?",
"Uploading and linking GCode...": "GCode hochladen und verknüpfen...",
"Active Print Job": "Aktiver Druckauftrag",
"Upload External GCode": "Externen GCode hochladen",
"Slicer": "Slicer",
"System Config": "Systemkonfiguration",
"Home All Axes": "Alle Achsen auf Nullposition",
"Pause/Resume Print": "Druck Pausieren/Fortsetzen",
"Slice": "Slicen",
"Network error": "Netzwerkfehler",
"Printer Control": "Drucker-Steuerung",
"Error saving settings": "Fehler beim Speichern der Einstellungen",
"page to set it up.": "Seite zum Einrichten.",
"Network Error: ": "Netzwerkfehler: ",
"3D Model Files (STL)": "3D-Modelldateien (STL)",
"You have uploaded": "Sie haben hochgeladen",
"Total Space Used": "Verwendeter Speicherplatz",
"Sliced Files (GCode)": "Geslicte Dateien (GCode)",
"You have sliced or uploaded": "Sie haben geslict oder hochgeladen",
"Default Storage Quotas (MB)": "Standard Speicherquoten (MB)",
"Guest STL Quota": "Gast STL Quoten",
"Unlimited": "Unbegrenzt",
"Guest GCode Quota": "Gast GCode Quoten",
"New User STL Quota": "Neuer Benutzer STL Quoten",
"New User GCode Quota": "Neuer Benutzer GCode Quoten",
"Quota": "Quote",
"GCode Storage Quota Exceeded. Please delete some files first.": "GCode Speicherplatz überschritten. Bitte löschen Sie zuerst einige Dateien.",
"Edit Quota": "Quota bearbeiten",
"Edit Quota for": "Quota bearbeiten für",
"Reset Password": "Passwort zurücksetzen",
"Reset Password for": "Passwort zurücksetzen für",
"Save": "Speichern",
"STL Quota": "STL Quote",
"GCode Quota": "GCode Quote",
"New Password": "Neues Passwort",
"Add User": "Benutzer hinzufügen",
"Password": "Passwort",
"Is Admin": "Ist Administrator",
"Create User": "Benutzer erstellen"
}

View File

@@ -113,5 +113,110 @@
"Default Support": "Default Support",
"Default Support Type": "Default Support Type",
"Default Quality Profile": "Default Quality Profile",
"Save Settings": "Save Settings"
"Save Settings": "Save Settings",
"You are editing a composite model. The existing composite will be updated and re-sliced. Continue?": "You are editing a composite model. The existing composite will be updated and re-sliced. Continue?",
"Select": "Select",
"OctoPrint settings updated": "OctoPrint settings updated",
"Settings updated successfully": "Settings updated successfully",
"This model has already been sliced. The existing GCode will be overwritten. Continue?": "This model has already been sliced. The existing GCode will be overwritten. Continue?",
"Print starting! Going to dashboard...": "Print starting! Going to dashboard...",
"Are you sure you want to delete this file?": "Are you sure you want to delete this file?",
"OctoPrint Base URL": "OctoPrint Base URL",
"Temperatures": "Temperatures",
"Notice": "Notice",
"Please upload valid .stl files!": "Please upload valid .stl files!",
"Print Time:": "Print Time:",
"System Configuration": "System Configuration",
"Command": "Command",
"Time Left:": "Time Left:",
"Yes": "Yes",
"Current State": "Current State",
"Error updating settings": "Error updating settings",
"Available Files on Printer": "Available Files on Printer",
"Control failed: ": "Control failed: ",
"Loading webcam stream...": "Loading webcam stream...",
"Live Webcam": "Live Webcam",
"No printable files found. Go slice some G-Code first!": "No printable files found. Go slice some G-Code first!",
"Save Connection Settings": "Save Connection Settings",
"Upload error.": "Upload error.",
"Validation Failed": "Validation Failed",
"Cancel Print": "Cancel Print",
"Send this file to print immediately?": "Send this file to print immediately?",
"Print Now": "Print Now",
"OctoPrint Panel (Embedded)": "OctoPrint Panel (Embedded)",
"Are you sure you want to perform this action?": "Are you sure you want to perform this action?",
"Control": "Control",
"Cancel": "Cancel",
"sent.": "sent.",
"The local IP address or hostname of your OctoPrint server.": "The local IP address or hostname of your OctoPrint server.",
"OctoPrint Panel": "OctoPrint Panel",
"General Operations": "General Operations",
"Confirm": "Confirm",
"Basic Control": "Basic Control",
"Size:": "Size:",
"Prepare Print": "Prepare Print",
"API Key / Application Key": "API Key / Application Key",
"Configuration Required:": "Configuration Required:",
"Paste API Key here": "Paste API Key here",
"Tool/Nozzle": "Tool/Nozzle",
"Pause/Resume": "Pause/Resume",
"Can be found in OctoPrint Settings -> Application Keys or API.": "Can be found in OctoPrint Settings -> Application Keys or API.",
"Preview": "Preview",
"Pause": "Pause",
"Bed": "Bed",
"Printer Status": "Printer Status",
"Printer": "Printer",
"Admin / OctoPrint": "Admin / OctoPrint",
"Absolute path to save locally sliced GCode files (e.g. OctoPrint uploads folder like \"/home/pi/.octoprint/uploads\"). Leave empty to use system default.": "Absolute path to save locally sliced GCode files (e.g. OctoPrint uploads folder like \"/home/pi/.octoprint/uploads\"). Leave empty to use system default.",
"Custom GCode Output Folder": "Custom GCode Output Folder",
"Go to Configuration": "Go to Configuration",
"OK": "OK",
"Connection Settings": "Connection Settings",
"OctoPrint Configuration": "OctoPrint Configuration",
"The OctoPrint URL is not set. Please go to the ": "The OctoPrint URL is not set. Please go to the ",
"Go to Print": "Go to Print",
"Time:": "Time:",
"Are you sure you want to cancel the print?": "Are you sure you want to cancel the print?",
"Uploading and linking GCode...": "Uploading and linking GCode...",
"Active Print Job": "Active Print Job",
"Upload External GCode": "Upload External GCode",
"Slicer": "Slicer",
"System Config": "System Config",
"Home All Axes": "Home All Axes",
"Pause/Resume Print": "Pause/Resume Print",
"Slice": "Slice",
"Upload failed.": "Upload failed.",
"Network error": "Network error",
"Upload Complete!": "Upload Complete!",
"Printer Control": "Printer Control",
"Error saving settings": "Error saving settings",
"page to set it up.": "page to set it up.",
"Network Error: ": "Network Error: ",
"Upload STL": "Upload STL",
"Please upload a valid .stl file!": "Please upload a valid .stl file!",
"3D Model Files (STL)": "3D Model Files (STL)",
"You have uploaded": "You have uploaded",
"Total Space Used": "Total Space Used",
"Sliced Files (GCode)": "Sliced Files (GCode)",
"You have sliced or uploaded": "You have sliced or uploaded",
"Default Storage Quotas (MB)": "Default Storage Quotas (MB)",
"Guest STL Quota": "Guest STL Quota",
"Unlimited": "Unlimited",
"Guest GCode Quota": "Guest GCode Quota",
"New User STL Quota": "New User STL Quota",
"New User GCode Quota": "New User GCode Quota",
"Quota": "Quota",
"GCode Storage Quota Exceeded. Please delete some files first.": "GCode Storage Quota Exceeded. Please delete some files first.",
"Edit Quota": "Edit Quota",
"Edit Quota for": "Edit Quota for",
"Reset Password": "Reset Password",
"Reset Password for": "Reset Password for",
"Save": "Save",
"STL Quota": "STL Quota",
"GCode Quota": "GCode Quota",
"New Password": "New Password",
"Add User": "Add User",
"Password": "Password",
"Is Admin": "Is Admin",
"Create User": "Create User"
}

View File

@@ -119,5 +119,104 @@
"Default Support": "默认支撑类型",
"Default Support Type": "默认支撑图案",
"Default Quality Profile": "默认质量配置",
"Save Settings": "保存设置"
"Save Settings": "保存设置",
"You are editing a composite model. The existing composite will be updated and re-sliced. Continue?": "您正在编辑合并模型。现有的组合将被更新并重新切片。继续吗?",
"Select": "选择",
"OctoPrint settings updated": "OctoPrint 设置已更新",
"Settings updated successfully": "设置更新成功",
"Print starting! Going to dashboard...": "打印开始!前往仪表板...",
"Are you sure you want to delete this file?": "您确定要删除此文件吗?",
"OctoPrint Base URL": "OctoPrint 基础 URL",
"Temperatures": "温度",
"Notice": "注意",
"Please upload valid .stl files!": "请上传有效的 .stl 文件!",
"Print Time:": "打印时间:",
"System Configuration": "系统配置",
"Command": "命令",
"Time Left:": "剩余时间:",
"Yes": "是",
"Current State": "当前状态",
"Error updating settings": "更新设置时出错",
"Available Files on Printer": "打印机上的可用文件",
"Control failed: ": "控制失败: ",
"Loading webcam stream...": "正在加载摄像头流...",
"Live Webcam": "实时摄像头",
"No printable files found. Go slice some G-Code first!": "未找到可打印文件。请先切片一些 G-Code",
"Save Connection Settings": "保存连接设置",
"Validation Failed": "验证失败",
"Cancel Print": "取消打印",
"Send this file to print immediately?": "立即发送此文件进行打印?",
"Print Now": "立即打印",
"OctoPrint Panel (Embedded)": "OctoPrint 面板 (嵌入)",
"Are you sure you want to perform this action?": "您确定要执行此操作吗?",
"Control": "控制",
"Cancel": "取消",
"sent.": "已发送。",
"The local IP address or hostname of your OctoPrint server.": "您的 OctoPrint 服务器的本地 IP 地址或主机名。",
"OctoPrint Panel": "OctoPrint 面板",
"General Operations": "通用操作",
"Confirm": "确认",
"Basic Control": "基本控制",
"Size:": "大小:",
"Prepare Print": "准备打印",
"API Key / Application Key": "API 密钥 / 应用程序密钥",
"Configuration Required:": "需要配置:",
"Paste API Key here": "在此处粘贴 API 密钥",
"Tool/Nozzle": "工具/喷嘴",
"Pause/Resume": "暂停/恢复",
"Can be found in OctoPrint Settings -> Application Keys or API.": "可以在 OctoPrint 设置 -> 应用程序密钥或 API 中找到。",
"Preview": "预览",
"Pause": "暂停",
"Bed": "热床",
"Printer Status": "打印机状态",
"Printer": "打印机",
"Admin / OctoPrint": "管理员 / OctoPrint",
"Absolute path to save locally sliced GCode files (e.g. OctoPrint uploads folder like \"/home/pi/.octoprint/uploads\"). Leave empty to use system default.": "保存本地切片 GCode 文件的绝对路径(例如 OctoPrint 的 uploads 文件夹:\"/home/pi/.octoprint/uploads\")。留空以使用系统默认值。",
"Custom GCode Output Folder": "自定义 GCode 输出文件夹",
"Go to Configuration": "前往配置",
"OK": "确定",
"Connection Settings": "连接设置",
"OctoPrint Configuration": "OctoPrint 配置",
"The OctoPrint URL is not set. Please go to the ": "未设置 OctoPrint URL。请前往",
"Go to Print": "前往打印",
"Time:": "时间:",
"Are you sure you want to cancel the print?": "您确定要取消打印吗?",
"Uploading and linking GCode...": "正在上传并链接 GCode...",
"Active Print Job": "当前打印任务",
"Upload External GCode": "上传外部 GCode",
"Slicer": "切片软件",
"System Config": "系统配置",
"Home All Axes": "全部轴归零",
"Pause/Resume Print": "暂停/恢复打印",
"Slice": "切片",
"Network error": "网络错误",
"Printer Control": "打印机控制",
"Error saving settings": "保存设置时出错",
"page to set it up.": "页面进行设置。",
"Network Error: ": "网络错误: ",
"3D Model Files (STL)": "3D 模型文件 (STL)",
"You have uploaded": "您已上传",
"Total Space Used": "占用空间",
"Sliced Files (GCode)": "已切片文件 (GCode)",
"You have sliced or uploaded": "您已切片或上传",
"Default Storage Quotas (MB)": "默认存储配额 (MB)",
"Guest STL Quota": "访客 STL 配额",
"Unlimited": "无限制",
"Guest GCode Quota": "访客 GCode 配额",
"New User STL Quota": "新用户 STL 配额",
"New User GCode Quota": "新用户 GCode 配额",
"Quota": "限额",
"GCode Storage Quota Exceeded. Please delete some files first.": "GCode 存储配额已超限,请先删除部分旧文件。",
"Edit Quota": "编辑配额",
"Edit Quota for": "编辑配额用于",
"Reset Password": "重置密码",
"Reset Password for": "重置密码 用户:",
"Save": "保存",
"STL Quota": "STL 配额",
"GCode Quota": "GCode 配额",
"New Password": "新密码",
"Add User": "添加用户",
"Password": "密码",
"Is Admin": "设为管理员",
"Create User": "创建用户"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,371 +0,0 @@
( 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 one or more lines are too long