Skip to content

Commit 2a512bc

Browse files
committed
✨ feat: add toShell/toSolid
1 parent ee02e99 commit 2a512bc

File tree

16 files changed

+134
-25
lines changed

16 files changed

+134
-25
lines changed

cpp/src/factory.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,6 @@ class ShapeFactory
188188
return ShapeResult{solidBuilder.Solid(), true, ""};
189189
}
190190

191-
static ShapeResult facesToSolid(const FaceArray &faces)
192-
{
193-
auto facesVec = vecFromJSArray<TopoDS_Face>(faces);
194-
return facesToSolid(facesVec);
195-
}
196-
197191
static ShapeResult cylinder(const Vector3 &normal, const Vector3 &center, double radius, double height)
198192
{
199193
gp_Ax2 ax2(Vector3::toPnt(center), Vector3::toDir(normal));
@@ -400,6 +394,33 @@ class ShapeFactory
400394
return ShapeResult{makeFace.Face(), true, ""};
401395
}
402396

397+
static ShapeResult shell(const FaceArray& faces) {
398+
std::vector<TopoDS_Face> facesVec = vecFromJSArray<TopoDS_Face>(faces);
399+
400+
TopoDS_Shell shell;
401+
BRep_Builder shellBuilder;
402+
shellBuilder.MakeShell(shell);
403+
for (const auto &face : facesVec)
404+
{
405+
shellBuilder.Add(shell, face);
406+
}
407+
408+
return ShapeResult{shell, true, ""};
409+
}
410+
411+
static ShapeResult solid(const ShellArray& shells) {
412+
std::vector<TopoDS_Shell> shellsVec = vecFromJSArray<TopoDS_Shell>(shells);
413+
414+
BRepBuilderAPI_MakeSolid makeSolid;
415+
for (auto shell : shellsVec) {
416+
makeSolid.Add(shell);
417+
}
418+
if (!makeSolid.IsDone()) {
419+
return ShapeResult{TopoDS_Shape(), false, "Failed to create solid"};
420+
}
421+
return ShapeResult{makeSolid.Solid(), true, ""};
422+
}
423+
403424
static ShapeResult makeThickSolidBySimple(const TopoDS_Shape &shape, double thickness) {
404425
BRepOffsetAPI_MakeThickSolid makeThickSolid;
405426
makeThickSolid.MakeThickSolidBySimple(shape, thickness);
@@ -530,6 +551,8 @@ EMSCRIPTEN_BINDINGS(ShapeFactory)
530551
.class_function("line", &ShapeFactory::line)
531552
.class_function("wire", &ShapeFactory::wire)
532553
.class_function("face", &ShapeFactory::face)
554+
.class_function("shell", &ShapeFactory::shell)
555+
.class_function("solid", &ShapeFactory::solid)
533556
.class_function("makeThickSolidBySimple", &ShapeFactory::makeThickSolidBySimple)
534557
.class_function("makeThickSolidByJoin", &ShapeFactory::makeThickSolidByJoin)
535558
.class_function("booleanCommon", &ShapeFactory::booleanCommon)

cpp/src/shape.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include <TopoDS.hxx>
4040
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
4141
#include <TopExp_Explorer.hxx>
42+
#include <BRepPrim_Builder.hxx>
43+
#include <BRepBuilderAPI_Sewing.hxx>
4244

4345

4446
using namespace emscripten;
@@ -185,6 +187,15 @@ class Shape {
185187
return fixer.Shape();
186188
}
187189

190+
static TopoDS_Shape sewing(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2) {
191+
BRepBuilderAPI_Sewing sewing;
192+
sewing.Add(shape1);
193+
sewing.Add(shape2);
194+
195+
sewing.Perform();
196+
return sewing.SewedShape();
197+
}
198+
188199
};
189200

190201
class Vertex {
@@ -337,6 +348,7 @@ EMSCRIPTEN_BINDINGS(Shape) {
337348
.class_function("removeFeature", &Shape::removeFeature)
338349
.class_function("removeSubShape", &Shape::removeSubShape)
339350
.class_function("replaceSubShape", &Shape::replaceSubShape)
351+
.class_function("sewing", &Shape::sewing)
340352
;
341353

342354
class_<Vertex>("Vertex")

cpp/src/shared.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ EMSCRIPTEN_BINDINGS(Shared) {
2626
register_type<EdgeArray>("Array<TopoDS_Edge>");
2727
register_type<FaceArray>("Array<TopoDS_Face>");
2828
register_type<WireArray>("Array<TopoDS_Wire>");
29+
register_type<ShellArray>("Array<TopoDS_Shell>");
2930
register_type<PntArray>("Array<gp_Pnt>");
3031

3132
register_optional<double>();

cpp/src/shared.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ EMSCRIPTEN_DECLARE_VAL_TYPE(NumberArray)
185185
EMSCRIPTEN_DECLARE_VAL_TYPE(EdgeArray)
186186
EMSCRIPTEN_DECLARE_VAL_TYPE(WireArray)
187187
EMSCRIPTEN_DECLARE_VAL_TYPE(FaceArray)
188+
EMSCRIPTEN_DECLARE_VAL_TYPE(ShellArray)
188189
EMSCRIPTEN_DECLARE_VAL_TYPE(ShapeArray)
189190
EMSCRIPTEN_DECLARE_VAL_TYPE(PointAndParameterArray)
190191
EMSCRIPTEN_DECLARE_VAL_TYPE(PntArray)

packages/chili-builder/src/ribbon.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ export const DefaultRibbon: RibbonTab[] = [
2525
"modify.move",
2626
"modify.rotate",
2727
"modify.mirror",
28-
["modify.explode", "modify.break", "modify.trim"],
29-
["modify.fillet", "modify.chamfer", "modify.split"],
28+
["modify.split", "modify.break", "modify.trim"],
29+
["modify.fillet", "modify.chamfer", "modify.explode"],
3030
["modify.delete", "modify.removeSubShapes", "modify.removeFeature"],
3131
],
3232
},
3333
{
3434
groupName: "ribbon.group.converter",
3535
items: [
36-
"convert.toWire",
37-
"convert.toFace",
3836
"convert.prism",
3937
"convert.sweep",
4038
"convert.revol",
39+
"convert.toWire",
40+
["convert.toFace", "convert.toShell", "convert.toSolid"],
4141
],
4242
},
4343
{

packages/chili-core/src/command/commandKeys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ const COMMAND_KEYS = [
1111
"convert.sweep",
1212
"convert.toFace",
1313
"convert.toWire",
14+
"convert.toShell",
15+
"convert.toSolid",
1416
"create.arc",
1517
"create.bezier",
1618
"create.box",

packages/chili-core/src/i18n/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ export default {
9696
"command.thickSolid": "Thick Solid",
9797
"command.toFace": "To Face",
9898
"command.toWire": "To Wire",
99+
"command.toShell": "To Shell",
100+
"command.toSolid": "To Solid",
99101
"command.trim": "Trim",
100102
"command.undo": "Undo",
101103
"common.angle": "Angle",

packages/chili-core/src/i18n/keys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ const I18N_KEYS = [
9090
"command.thickSolid",
9191
"command.toFace",
9292
"command.toWire",
93+
"command.toShell",
94+
"command.toSolid",
9395
"command.trim",
9496
"command.undo",
9597
"common.angle",

packages/chili-core/src/i18n/zh-cn.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ export default {
9595
"command.thickSolid": "抽壳",
9696
"command.toFace": "转面",
9797
"command.toWire": "转多段线",
98+
"command.toShell": "转壳体",
99+
"command.toSolid": "转实体",
98100
"command.trim": "修剪",
99101
"command.undo": "撤销",
100102
"common.angle": "角度",

packages/chili-core/src/shape/shapeFactory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33

44
import { Result } from "../foundation";
55
import { Plane, Ray, XYZ, XYZLike } from "../math";
6-
import { ICompound, IEdge, IFace, IShape, ISolid, IVertex, IWire } from "./shape";
6+
import { ICompound, IEdge, IFace, IShape, IShell, ISolid, IVertex, IWire } from "./shape";
77
import { IShapeConverter } from "./shapeConverter";
88

99
export interface IShapeFactory {
1010
readonly kernelName: string;
1111
readonly converter: IShapeConverter;
1212
face(wire: IWire[]): Result<IFace>;
13+
shell(faces: IFace[]): Result<IShell>;
14+
solid(shells: IShell[]): Result<ISolid>;
1315
bezier(points: XYZLike[], weights?: number[]): Result<IEdge>;
1416
point(point: XYZLike): Result<IVertex>;
1517
line(start: XYZLike, end: XYZLike): Result<IEdge>;

packages/chili-wasm/lib/chili-wasm.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,9 @@ interface EmbindModule {
601601
wire(_0: Array<TopoDS_Edge>): ShapeResult;
602602
fillet(_0: TopoDS_Shape, _1: Array<TopoDS_Edge>, _2: number): ShapeResult;
603603
chamfer(_0: TopoDS_Shape, _1: Array<TopoDS_Edge>, _2: number): ShapeResult;
604+
shell(_0: Array<TopoDS_Face>): ShapeResult;
604605
face(_0: Array<TopoDS_Wire>): ShapeResult;
606+
solid(_0: Array<TopoDS_Shell>): ShapeResult;
605607
cone(_0: Vector3, _1: Vector3, _2: number, _3: number, _4: number): ShapeResult;
606608
sphere(_0: Vector3, _1: number): ShapeResult;
607609
ellipsoid(_0: Vector3, _1: Vector3, _2: Vector3, _3: number, _4: number, _5: number): ShapeResult;
@@ -779,6 +781,7 @@ interface EmbindModule {
779781
sectionSS(_0: TopoDS_Shape, _1: TopoDS_Shape): TopoDS_Shape;
780782
isClosed(_0: TopoDS_Shape): boolean;
781783
replaceSubShape(_0: TopoDS_Shape, _1: TopoDS_Shape, _2: TopoDS_Shape): TopoDS_Shape;
784+
sewing(_0: TopoDS_Shape, _1: TopoDS_Shape): TopoDS_Shape;
782785
findAncestor(_0: TopoDS_Shape, _1: TopoDS_Shape, _2: TopAbs_ShapeEnum): Array<TopoDS_Shape>;
783786
findSubShapes(_0: TopoDS_Shape, _1: TopAbs_ShapeEnum): Array<TopoDS_Shape>;
784787
iterShape(_0: TopoDS_Shape): Array<TopoDS_Shape>;

packages/chili-wasm/lib/chili-wasm.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5244,27 +5244,27 @@ var Module = (() => {
52445244
w: __embind_register_enum,
52455245
h: __embind_register_enum_value,
52465246
C: __embind_register_float,
5247-
q: __embind_register_integer,
5248-
j: __embind_register_memory_view,
5247+
r: __embind_register_integer,
5248+
l: __embind_register_memory_view,
52495249
v: __embind_register_optional,
52505250
fa: __embind_register_std_string,
52515251
z: __embind_register_std_wstring,
5252-
k: __embind_register_user_type,
5252+
j: __embind_register_user_type,
52535253
p: __embind_register_value_object,
52545254
m: __embind_register_value_object_field,
52555255
ha: __embind_register_void,
52565256
G: __emscripten_lookup_name,
52575257
K: __emscripten_runtime_keepalive_clear,
5258-
u: __emval_as,
5259-
s: __emval_call_method,
5258+
q: __emval_as,
5259+
t: __emval_call_method,
52605260
d: __emval_decref,
5261-
r: __emval_get_method_caller,
5261+
s: __emval_get_method_caller,
52625262
E: __emval_get_property,
52635263
f: __emval_incref,
5264-
t: __emval_new_array,
5264+
u: __emval_new_array,
52655265
B: __emval_new_array_from_memory_view,
52665266
ia: __emval_new_cstring,
5267-
l: __emval_run_destructors,
5267+
k: __emval_run_destructors,
52685268
n: __emval_take_value,
52695269
O: __localtime_js,
52705270
F: __setitimer_js,
2.99 KB
Binary file not shown.

packages/chili-wasm/src/factory.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
IShape,
99
IShapeConverter,
1010
IShapeFactory,
11+
IShell,
1112
ISolid,
1213
IVertex,
1314
IWire,
@@ -209,6 +210,12 @@ export class ShapeFactory implements IShapeFactory {
209210
wire(edges: IEdge[]): Result<IWire> {
210211
return convertShapeResult(wasm.ShapeFactory.wire(ensureOccShape(edges))) as Result<IWire>;
211212
}
213+
shell(faces: IFace[]): Result<IShell> {
214+
return convertShapeResult(wasm.ShapeFactory.shell(ensureOccShape(faces))) as Result<IShell>;
215+
}
216+
solid(shells: IShell[]): Result<ISolid> {
217+
return convertShapeResult(wasm.ShapeFactory.solid(ensureOccShape(shells))) as Result<ISolid>;
218+
}
212219
prism(shape: IShape, vec: XYZ): Result<IShape> {
213220
if (vec.length() === 0) {
214221
return Result.err(`The vector length is 0, the prism cannot be created.`);

packages/chili/src/commands/create/converter.ts

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
import {
55
AsyncController,
66
CancelableCommand,
7+
EditableShapeNode,
78
GeometryNode,
89
IDocument,
910
IEdge,
11+
IFace,
1012
INode,
13+
IShape,
1114
IShapeFilter,
15+
IShell,
1216
PubSub,
1317
Result,
1418
ShapeNode,
@@ -36,15 +40,21 @@ abstract class ConvertCommand extends CancelableCommand {
3640
this.document.visual.update();
3741
PubSub.default.pub("showToast", "toast.success");
3842
}
43+
44+
models.forEach((x) => x.parent?.remove(x));
3945
});
4046
}
4147

4248
protected abstract create(document: IDocument, models: INode[]): Result<GeometryNode>;
49+
protected shapeFilter(): IShapeFilter {
50+
return {
51+
allow: (shape: IShape) =>
52+
shape.shapeType === ShapeType.Edge || shape.shapeType === ShapeType.Wire,
53+
};
54+
}
4355

4456
async getOrPickModels(document: IDocument) {
45-
const filter: IShapeFilter = {
46-
allow: (shape) => shape.shapeType === ShapeType.Edge || shape.shapeType === ShapeType.Wire,
47-
};
57+
const filter = this.shapeFilter();
4858
let models = this._getSelectedModels(document, filter);
4959
document.selection.clearSelection();
5060
if (models.length > 0) return models;
@@ -82,7 +92,6 @@ export class ConvertToWire extends ConvertCommand {
8292
const shape = wireBody.generateShape();
8393
if (!shape.isOk) return Result.err(shape.error);
8494

85-
models.forEach((x) => x.parent?.remove(x));
8695
return Result.ok(wireBody);
8796
}
8897
}
@@ -99,7 +108,50 @@ export class ConvertToFace extends ConvertCommand {
99108
const shape = wireBody.generateShape();
100109
if (!shape.isOk) return Result.err(shape.error);
101110

102-
models.forEach((x) => x.parent?.remove(x));
103111
return Result.ok(wireBody);
104112
}
105113
}
114+
115+
@command({
116+
name: "convert.toShell",
117+
display: "command.toShell",
118+
icon: "icon-toShell",
119+
})
120+
export class ConvertToShell extends ConvertCommand {
121+
protected override shapeFilter(): IShapeFilter {
122+
return {
123+
allow: (shape: IShape) => shape.shapeType === ShapeType.Face,
124+
};
125+
}
126+
127+
protected override create(document: IDocument, models: ShapeNode[]): Result<GeometryNode> {
128+
const faces = models.map((x) => x.shape.value.copy()) as IFace[];
129+
const shape = this.application.shapeFactory.shell(faces);
130+
if (!shape.isOk) return Result.err(shape.error);
131+
132+
const shell = new EditableShapeNode(document, "shell", shape);
133+
return Result.ok(shell);
134+
}
135+
}
136+
137+
@command({
138+
name: "convert.toSolid",
139+
display: "command.toSolid",
140+
icon: "icon-toSolid",
141+
})
142+
export class ConvertToSolid extends ConvertCommand {
143+
protected override shapeFilter(): IShapeFilter {
144+
return {
145+
allow: (shape: IShape) => shape.shapeType === ShapeType.Shell,
146+
};
147+
}
148+
149+
protected override create(document: IDocument, models: ShapeNode[]): Result<GeometryNode> {
150+
const faces = models.map((x) => x.shape.value.copy()) as IShell[];
151+
const shape = this.application.shapeFactory.solid(faces);
152+
if (!shape.isOk) return Result.err(shape.error);
153+
154+
const solid = new EditableShapeNode(document, "solid", shape);
155+
return Result.ok(solid);
156+
}
157+
}

public/iconfont.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)