Skip to content

Commit b7caf91

Browse files
committedFeb 23, 2025·
✨ feat: added the .brep format
1 parent 458f411 commit b7caf91

File tree

3 files changed

+128
-55
lines changed

3 files changed

+128
-55
lines changed
 

‎packages/chili-builder/src/appBuilder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { Application, CommandService, EditEventHandler, EditorService, HotkeyService } from "chili";
44
import {
5-
DefaultDataExchange,
65
I18n,
76
IDataExchange,
87
IDocument,
@@ -15,6 +14,7 @@ import {
1514
Logger,
1615
} from "chili-core";
1716
import { IAdditionalModule } from "./additionalModule";
17+
import { DefaultDataExchange } from "./defaultDataExchange";
1818

1919
export class AppBuilder {
2020
protected readonly _inits: (() => Promise<void>)[] = [];
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license.
2+
3+
import {
4+
EditableShapeNode,
5+
I18n,
6+
IDataExchange,
7+
IDocument,
8+
IShape,
9+
PubSub,
10+
Result,
11+
ShapeNode,
12+
VisualNode,
13+
} from "chili-core";
14+
15+
async function importBrep(document: IDocument, file: File) {
16+
const shape = document.application.shapeFactory.converter.convertFromBrep(await file.text());
17+
if (!shape.isOk) {
18+
return Result.err(shape.error);
19+
}
20+
return Result.ok(new EditableShapeNode(document, file.name, shape.value));
21+
}
22+
23+
async function exportBrep(document: IDocument, shapes: IShape[]) {
24+
const comp = document.application.shapeFactory.combine(shapes);
25+
if (!comp.isOk) {
26+
return Result.err(comp.error);
27+
}
28+
return document.application.shapeFactory.converter.convertToBrep(comp.value);
29+
}
30+
31+
export class DefaultDataExchange implements IDataExchange {
32+
importFormats(): string[] {
33+
return [".step", ".stp", ".iges", ".igs", ".brep"];
34+
}
35+
36+
exportFormats(): string[] {
37+
return [".step", ".iges", ".brep"];
38+
}
39+
40+
async import(document: IDocument, files: FileList | File[]): Promise<void> {
41+
for (const file of files) {
42+
await this.handleSingleFileImport(document, file);
43+
}
44+
}
45+
46+
private async handleSingleFileImport(document: IDocument, file: File) {
47+
const nodeResult = file.name.endsWith(".brep")
48+
? await importBrep(document, file)
49+
: await this.handleStepIgesImport(document, file);
50+
51+
if (!nodeResult?.isOk) return;
52+
53+
const node = nodeResult.value;
54+
node.name = file.name;
55+
document.addNode(node);
56+
document.visual.update();
57+
}
58+
59+
private async handleStepIgesImport(document: IDocument, file: File) {
60+
const content = new Uint8Array(await file.arrayBuffer());
61+
62+
if (this.isStepFile(file.name)) {
63+
return document.application.shapeFactory.converter.convertFromSTEP(document, content);
64+
}
65+
66+
if (this.isIgesFile(file.name)) {
67+
return document.application.shapeFactory.converter.convertFromIGES(document, content);
68+
}
69+
70+
alert(I18n.translate("error.import.unsupportedFileType:{0}", file.name));
71+
return undefined;
72+
}
73+
74+
async export(type: string, nodes: VisualNode[]): Promise<BlobPart[] | undefined> {
75+
if (!this.validateExportType(type)) return;
76+
77+
const shapes = this.getExportShapes(nodes);
78+
if (!shapes.length) return;
79+
80+
const shapeResult = await this.convertShapes(type, nodes[0].document, shapes);
81+
return this.handleExportResult(shapeResult);
82+
}
83+
84+
private validateExportType(type: string): boolean {
85+
const isValid = this.exportFormats().includes(type);
86+
!isValid && PubSub.default.pub("showToast", "error.import.unsupportedFileType:{0}", type);
87+
return isValid;
88+
}
89+
90+
private getExportShapes(nodes: VisualNode[]): IShape[] {
91+
const shapes = nodes.filter((x): x is ShapeNode => x instanceof ShapeNode).map((x) => x.shape.value);
92+
93+
!shapes.length && PubSub.default.pub("showToast", "error.export.noNodeCanBeExported");
94+
return shapes;
95+
}
96+
97+
private async convertShapes(type: string, doc: IDocument, shapes: IShape[]) {
98+
if (type === ".step") return this.handleStepExport(doc, shapes);
99+
if (type === ".iges") return this.handleIgesExport(doc, shapes);
100+
return exportBrep(doc, shapes);
101+
}
102+
103+
private handleStepExport(doc: IDocument, shapes: IShape[]) {
104+
return doc.application.shapeFactory.converter.convertToSTEP(...shapes);
105+
}
106+
107+
private handleIgesExport(doc: IDocument, shapes: IShape[]) {
108+
return doc.application.shapeFactory.converter.convertToIGES(...shapes);
109+
}
110+
111+
private handleExportResult(result: Result<string> | undefined) {
112+
if (!result?.isOk) {
113+
PubSub.default.pub("showToast", "error.default:{0}", result?.error);
114+
return undefined;
115+
}
116+
return [result.value];
117+
}
118+
119+
private isStepFile(filename: string) {
120+
return filename.endsWith(".step") || filename.endsWith(".stp");
121+
}
122+
123+
private isIgesFile(filename: string) {
124+
return filename.endsWith(".iges") || filename.endsWith(".igs");
125+
}
126+
}
Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,11 @@
11
// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license.
22

33
import { IDocument } from "./document";
4-
import { PubSub, Result } from "./foundation";
5-
import { I18n } from "./i18n";
6-
import { FolderNode, ShapeNode, VisualNode } from "./model";
4+
import { VisualNode } from "./model";
75

86
export interface IDataExchange {
97
importFormats(): string[];
108
exportFormats(): string[];
119
import(document: IDocument, files: FileList | File[]): Promise<void>;
1210
export(type: string, nodes: VisualNode[]): Promise<BlobPart[] | undefined>;
1311
}
14-
15-
export class DefaultDataExchange implements IDataExchange {
16-
importFormats(): string[] {
17-
return [".step", ".stp", ".iges", ".igs"];
18-
}
19-
20-
exportFormats(): string[] {
21-
return [".step", ".iges"];
22-
}
23-
24-
async import(document: IDocument, files: FileList | File[]): Promise<void> {
25-
for (const file of files) {
26-
let content = new Uint8Array(await file.arrayBuffer());
27-
let shape: Result<FolderNode>;
28-
if (file.name.endsWith(".step") || file.name.endsWith(".stp")) {
29-
shape = document.application.shapeFactory.converter.convertFromSTEP(document, content);
30-
} else if (file.name.endsWith(".iges") || file.name.endsWith(".igs")) {
31-
shape = document.application.shapeFactory.converter.convertFromIGES(document, content);
32-
} else {
33-
alert(I18n.translate("error.import.unsupportedFileType:{0}", file.name));
34-
continue;
35-
}
36-
if (!shape.isOk) {
37-
PubSub.default.pub("showToast", "error.default:{0}", shape.error);
38-
continue;
39-
}
40-
shape.value.name = file.name;
41-
document.addNode(shape.value);
42-
document.visual.update();
43-
}
44-
}
45-
46-
async export(type: string, nodes: VisualNode[]): Promise<BlobPart[] | undefined> {
47-
let shapes = nodes.filter((x) => x instanceof ShapeNode).map((x) => x.shape.value);
48-
if (shapes.length === 0) {
49-
PubSub.default.pub("showToast", "error.export.noNodeCanBeExported");
50-
return undefined;
51-
}
52-
let factory = nodes[0].document.application.shapeFactory.converter.convertToIGES;
53-
if (type === ".step") {
54-
factory = nodes[0].document.application.shapeFactory.converter.convertToSTEP;
55-
}
56-
let shapeString = factory(...shapes);
57-
if (!shapeString.isOk) {
58-
PubSub.default.pub("showToast", "error.default:{0}", shapeString.error);
59-
return undefined;
60-
}
61-
62-
return [shapeString.value];
63-
}
64-
}

0 commit comments

Comments
 (0)
Please sign in to comment.