fix: cleanup

This commit is contained in:
hyper 2026-03-17 12:19:15 +08:00
parent c3f71f8be1
commit 352b17071c
2 changed files with 5 additions and 135 deletions

View File

@ -1,6 +1,6 @@
import * as THREE from "three"; import * as THREE from "three";
import { exportTo3MF } from "three-3mf-exporter"; import { exportTo3MF } from "three-3mf-exporter";
import type { TraceResult, PathData } from "./image-tracer"; import type { TraceResult } from "./image-tracer";
export interface ExtrusionSettings { export interface ExtrusionSettings {
size: number; // 模型整体尺寸 (mm) size: number; // 模型整体尺寸 (mm)
@ -57,41 +57,13 @@ export async function generate3MF(
const layer = traceResult.layers.find((l) => l.id === layerSetting.id); const layer = traceResult.layers.find((l) => l.id === layerSetting.id);
if (!layer) continue; if (!layer) continue;
// 为该图层的所有路径创建形状
const shapes: THREE.Shape[] = [];
for (const path of layer.paths) {
if (path.points.length < 2) continue;
const shape = createShapeFromPath(path, scale, offsetX, offsetY);
if (shape) {
shapes.push(shape);
}
}
if (shapes.length === 0) continue;
// 创建挤压几何体 // 创建挤压几何体
const extrudeSettings: THREE.ExtrudeGeometryOptions = { const extrudeSettings: THREE.ExtrudeGeometryOptions = {
depth: layerSetting.thickness, depth: layerSetting.thickness,
curveSegments: 36, curveSegments: 36,
bevelEnabled: false, bevelEnabled: false,
}; };
const geometry: THREE.ExtrudeGeometry = new THREE.ExtrudeGeometry(layer.paths, extrudeSettings);
// 如果有多个形状,创建多个几何体并合并
const geometries: THREE.ExtrudeGeometry[] = [];
for (const shape of shapes) {
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
geometries.push(geometry);
}
// 合并同一图层的几何体
let combinedGeometry;
if (geometries.length === 1) {
combinedGeometry = geometries[0];
} else {
combinedGeometry = mergeGeometries(geometries);
}
// 为该图层生成颜色 // 为该图层生成颜色
const color = generateLayerColor(layerIndex); const color = generateLayerColor(layerIndex);
@ -101,7 +73,7 @@ export async function generate3MF(
roughness: 0.7, roughness: 0.7,
}); });
const mesh = new THREE.Mesh(combinedGeometry, material); const mesh = new THREE.Mesh(geometry, material);
// 设置图层高度(堆叠) // 设置图层高度(堆叠)
mesh.position.y = currentHeight; mesh.position.y = currentHeight;
@ -134,100 +106,4 @@ export async function generate3MF(
}); });
return blob; return blob;
} }
/**
* Three.js
*/
function createShapeFromPath(
path: PathData,
scale: number,
offsetX: number,
offsetY: number
): THREE.Shape | null {
if (path.points.length < 2) return null;
const shape = new THREE.Shape();
// 移动到起点
const startPoint = path.points[0];
shape.moveTo(
(startPoint.x + offsetX) * scale,
(startPoint.y + offsetY) * scale
);
// 绘制线段到后续点
for (let i = 1; i < path.points.length; i++) {
const point = path.points[i];
shape.lineTo(
(point.x + offsetX) * scale,
(point.y + offsetY) * scale
);
}
// 如果是闭合路径,闭合形状
if (path.isClosed) {
shape.closePath();
}
return shape;
}
/**
*
*/
function mergeGeometries(
geometries: THREE.ExtrudeGeometry[]
): THREE.ExtrudeGeometry {
const mergedGeometry = geometries[0].clone();
for (let i = 1; i < geometries.length; i++) {
const geometry = geometries[i];
const positionAttribute = geometry.getAttribute("position");
const normalAttribute = geometry.getAttribute("normal");
const uvAttribute = geometry.getAttribute("uv");
if (positionAttribute) {
const positions = mergedGeometry.getAttribute("position");
const newPositions = new Float32Array(
positions.array.length + positionAttribute.array.length
);
newPositions.set(positions.array);
newPositions.set(positionAttribute.array, positions.array.length);
mergedGeometry.setAttribute(
"position",
new THREE.BufferAttribute(newPositions, 3)
);
}
if (normalAttribute) {
const normals = mergedGeometry.getAttribute("normal");
const newNormals = new Float32Array(
normals.array.length + normalAttribute.array.length
);
newNormals.set(normals.array);
newNormals.set(normalAttribute.array, normals.array.length);
mergedGeometry.setAttribute(
"normal",
new THREE.BufferAttribute(newNormals, 3)
);
}
if (uvAttribute) {
const uvs = mergedGeometry.getAttribute("uv");
const newUvs = new Float32Array(
uvs.array.length + uvAttribute.array.length
);
newUvs.set(uvs.array);
newUvs.set(uvAttribute.array, uvs.array.length);
mergedGeometry.setAttribute(
"uv",
new THREE.BufferAttribute(newUvs, 2)
);
}
}
mergedGeometry.computeVertexNormals();
return mergedGeometry;
}

View File

@ -1,4 +1,4 @@
import { ImageTracer, type TraceData, type OutlinedArea, type SvgLineAttributes, Options } from "@image-tracer-ts/core"; import { ImageTracer, Options } from "@image-tracer-ts/core";
//@ts-ignore //@ts-ignore
import {SVGLoader, SVGResult} from "three/examples/jsm/loaders/SVGLoader"; import {SVGLoader, SVGResult} from "three/examples/jsm/loaders/SVGLoader";
import {Color, ShapePath, Shape} from "three"; import {Color, ShapePath, Shape} from "three";
@ -26,12 +26,6 @@ export interface TraceResult {
layers: TracedLayer[]; layers: TracedLayer[];
} }
interface SvgPath {
color: string;
d: string;
path: PathData;
}
/** /**
* *
* @param image - * @param image -