1use cxx::UniquePtr;
2use opencascade_sys::ffi::{
3 cylinder_to_surface, ellipse_to_HandleGeom2d_Curve, ellipse_value, gp_Ax2_ctor, gp_Ax2d_ctor,
4 gp_Ax3_from_gp_Ax2, gp_DZ, gp_Dir2d_ctor, gp_OX, handle_geom_plane_location,
5 new_HandleGeomCurve_from_HandleGeom_TrimmedCurve, new_HandleGeomPlane_from_HandleGeomSurface,
6 new_list_of_shape, new_point, new_point_2d, new_transform, new_vec, shape_list_append_face,
7 type_name, write_stl, BRepAlgoAPI_Fuse_ctor, BRepBuilderAPI_MakeEdge_CurveSurface2d,
8 BRepBuilderAPI_MakeEdge_HandleGeomCurve, BRepBuilderAPI_MakeFace_wire,
9 BRepBuilderAPI_MakeWire_ctor, BRepBuilderAPI_MakeWire_edge_edge,
10 BRepBuilderAPI_MakeWire_edge_edge_edge, BRepBuilderAPI_Transform_ctor,
11 BRepFilletAPI_MakeFillet_ctor, BRepLibBuildCurves3d, BRepMesh_IncrementalMesh_ctor,
12 BRepOffsetAPI_MakeThickSolid_ctor, BRepOffsetAPI_ThruSections_ctor,
13 BRepPrimAPI_MakeCylinder_ctor, BRepPrimAPI_MakePrism_ctor, BRep_Builder_ctor,
14 BRep_Builder_upcast_to_topods_builder, BRep_Tool_Surface, DynamicType, ExplorerCurrentShape,
15 GCE2d_MakeSegment_point_point, GC_MakeArcOfCircle_Value, GC_MakeArcOfCircle_point_point_point,
16 GC_MakeSegment_Value, GC_MakeSegment_point_point, Geom2d_Ellipse_ctor,
17 Geom2d_TrimmedCurve_ctor, Geom_CylindricalSurface_ctor, HandleGeom2d_TrimmedCurve_to_curve,
18 MakeThickSolidByJoin, StlAPI_Writer_ctor, TopAbs_ShapeEnum, TopExp_Explorer_ctor,
19 TopoDS_Compound_as_shape, TopoDS_Compound_ctor, TopoDS_Face, TopoDS_Face_to_owned,
20 TopoDS_cast_to_edge, TopoDS_cast_to_face, TopoDS_cast_to_wire,
21};
22
23pub fn main() {
25 let height = 70.0;
26 let width = 50.0;
27 let thickness = 30.0;
28
29 let point_1 = new_point(-width / 2.0, 0.0, 0.0);
31 let point_2 = new_point(-width / 2.0, -thickness / 4.0, 0.0);
32 let point_3 = new_point(0.0, -thickness / 2.0, 0.0);
33 let point_4 = new_point(width / 2.0, -thickness / 4.0, 0.0);
34 let point_5 = new_point(width / 2.0, 0.0, 0.0);
35
36 let arc = GC_MakeArcOfCircle_point_point_point(&point_2, &point_3, &point_4);
38 let segment_1 = GC_MakeSegment_point_point(&point_1, &point_2);
39 let segment_2 = GC_MakeSegment_point_point(&point_4, &point_5);
40
41 let mut edge_1 = BRepBuilderAPI_MakeEdge_HandleGeomCurve(
42 &new_HandleGeomCurve_from_HandleGeom_TrimmedCurve(&GC_MakeSegment_Value(&segment_1)),
43 );
44
45 let mut edge_2 = BRepBuilderAPI_MakeEdge_HandleGeomCurve(
46 &new_HandleGeomCurve_from_HandleGeom_TrimmedCurve(&GC_MakeArcOfCircle_Value(&arc)),
47 );
48
49 let mut edge_3 = BRepBuilderAPI_MakeEdge_HandleGeomCurve(
50 &new_HandleGeomCurve_from_HandleGeom_TrimmedCurve(&GC_MakeSegment_Value(&segment_2)),
51 );
52
53 let mut wire = BRepBuilderAPI_MakeWire_edge_edge_edge(
54 edge_1.pin_mut().Edge(),
55 edge_2.pin_mut().Edge(),
56 edge_3.pin_mut().Edge(),
57 );
58
59 let x_axis = gp_OX();
60
61 let mut transform = new_transform();
62 transform.pin_mut().set_mirror_axis(x_axis);
63
64 let mut brep_transform =
66 BRepBuilderAPI_Transform_ctor(wire.pin_mut().Shape(), &transform, false);
67 let mirrored_shape = brep_transform.pin_mut().Shape();
68 let mirrored_wire = TopoDS_cast_to_wire(mirrored_shape);
69
70 let mut make_wire = BRepBuilderAPI_MakeWire_ctor();
71 make_wire.pin_mut().add_wire(wire.pin_mut().Wire());
72 make_wire.pin_mut().add_wire(mirrored_wire);
73
74 let wire_profile = make_wire.pin_mut().Wire();
75
76 let mut face_profile = BRepBuilderAPI_MakeFace_wire(wire_profile, false);
77 let prism_vec = new_vec(0.0, 0.0, height);
78 let mut body =
80 BRepPrimAPI_MakePrism_ctor(face_profile.pin_mut().Shape(), &prism_vec, false, true);
81
82 let mut make_fillet = BRepFilletAPI_MakeFillet_ctor(body.pin_mut().Shape());
83 let mut edge_explorer =
84 TopExp_Explorer_ctor(body.pin_mut().Shape(), TopAbs_ShapeEnum::TopAbs_EDGE);
85
86 while edge_explorer.More() {
87 let edge = TopoDS_cast_to_edge(edge_explorer.Current());
88 make_fillet.pin_mut().add_edge(thickness / 12.0, edge);
89 edge_explorer.pin_mut().Next();
90 }
91
92 let body_shape = make_fillet.pin_mut().Shape();
93
94 let neck_location = new_point(0.0, 0.0, height);
96 let neck_axis = gp_DZ();
97 let neck_coord_system = gp_Ax2_ctor(&neck_location, neck_axis);
98
99 let neck_radius = thickness / 4.0;
100 let neck_height = height / 10.0;
101
102 let mut cylinder = BRepPrimAPI_MakeCylinder_ctor(&neck_coord_system, neck_radius, neck_height);
103 let cylinder_shape = cylinder.pin_mut().Shape();
104
105 let mut fuse_neck = BRepAlgoAPI_Fuse_ctor(body_shape, cylinder_shape);
106 let body_shape = fuse_neck.pin_mut().Shape();
107
108 let mut face_explorer = TopExp_Explorer_ctor(body_shape, TopAbs_ShapeEnum::TopAbs_FACE);
110 let mut z_max = -1.0;
111 let mut top_face: Option<UniquePtr<TopoDS_Face>> = None;
112
113 while face_explorer.More() {
114 let shape = ExplorerCurrentShape(&face_explorer);
115 let face = TopoDS_cast_to_face(&shape);
116
117 let surface = BRep_Tool_Surface(face);
118 let dynamic_type = DynamicType(&surface);
119 let name = type_name(dynamic_type);
120
121 if name == "Geom_Plane" {
122 let plane_handle = new_HandleGeomPlane_from_HandleGeomSurface(&surface);
123 let plane_location = handle_geom_plane_location(&plane_handle);
124
125 let plane_z = plane_location.Z();
126 if plane_z > z_max {
127 z_max = plane_z;
128 top_face = Some(TopoDS_Face_to_owned(face));
129 }
130 }
131
132 face_explorer.pin_mut().Next();
133 }
134
135 let top_face = top_face.unwrap();
136
137 let mut faces_to_remove = new_list_of_shape();
138 shape_list_append_face(faces_to_remove.pin_mut(), &top_face);
139
140 let mut solid_maker = BRepOffsetAPI_MakeThickSolid_ctor();
141 MakeThickSolidByJoin(
142 solid_maker.pin_mut(),
143 body_shape,
144 &faces_to_remove,
145 -thickness / 50.0,
146 1.0e-3,
147 );
148
149 let body_shape = solid_maker.pin_mut().Shape();
150
151 let cylinder_axis = gp_Ax3_from_gp_Ax2(&neck_coord_system);
153 let cylinder_1 = Geom_CylindricalSurface_ctor(&cylinder_axis, neck_radius * 0.99);
154 let cylinder_1 = cylinder_to_surface(&cylinder_1);
155 let cylinder_2 = Geom_CylindricalSurface_ctor(&cylinder_axis, neck_radius * 1.05);
156 let cylinder_2 = cylinder_to_surface(&cylinder_2);
157
158 let a_pnt = new_point_2d(std::f64::consts::TAU, neck_height / 2.0);
159 let a_dir = gp_Dir2d_ctor(std::f64::consts::TAU, neck_height / 4.0);
160 let thread_axis = gp_Ax2d_ctor(&a_pnt, &a_dir);
161
162 let a_major = std::f64::consts::TAU;
163 let a_minor = neck_height / 10.0;
164
165 let ellipse_1 = Geom2d_Ellipse_ctor(&thread_axis, a_major, a_minor);
166 let ellipse_1_handle = ellipse_to_HandleGeom2d_Curve(&ellipse_1);
167 let ellipse_2 = Geom2d_Ellipse_ctor(&thread_axis, a_major, a_minor / 4.0);
168 let ellipse_2_handle = ellipse_to_HandleGeom2d_Curve(&ellipse_2);
169 let arc_1 = Geom2d_TrimmedCurve_ctor(&ellipse_1_handle, 0.0, std::f64::consts::PI);
170 let arc_1 = HandleGeom2d_TrimmedCurve_to_curve(&arc_1);
171 let arc_2 = Geom2d_TrimmedCurve_ctor(&ellipse_2_handle, 0.0, std::f64::consts::PI);
172 let arc_2 = HandleGeom2d_TrimmedCurve_to_curve(&arc_2);
173
174 let ellipse_point_1 = ellipse_value(&ellipse_1, 0.0);
175 let ellipse_point_2 = ellipse_value(&ellipse_1, std::f64::consts::PI);
176 let thread_segment = GCE2d_MakeSegment_point_point(&ellipse_point_1, &ellipse_point_2);
177 let thread_segment = HandleGeom2d_TrimmedCurve_to_curve(&thread_segment);
178
179 let mut edge_1_on_surface_1 = BRepBuilderAPI_MakeEdge_CurveSurface2d(&arc_1, &cylinder_1);
180 let mut edge_2_on_surface_1 =
181 BRepBuilderAPI_MakeEdge_CurveSurface2d(&thread_segment, &cylinder_1);
182 let mut edge_1_on_surface_2 = BRepBuilderAPI_MakeEdge_CurveSurface2d(&arc_2, &cylinder_2);
183 let mut edge_2_on_surface_2 =
184 BRepBuilderAPI_MakeEdge_CurveSurface2d(&thread_segment, &cylinder_2);
185
186 let mut threading_wire_1 = BRepBuilderAPI_MakeWire_edge_edge(
187 edge_1_on_surface_1.pin_mut().Edge(),
188 edge_2_on_surface_1.pin_mut().Edge(),
189 );
190 let mut threading_wire_2 = BRepBuilderAPI_MakeWire_edge_edge(
191 edge_1_on_surface_2.pin_mut().Edge(),
192 edge_2_on_surface_2.pin_mut().Edge(),
193 );
194
195 BRepLibBuildCurves3d(threading_wire_1.pin_mut().Shape());
197 BRepLibBuildCurves3d(threading_wire_2.pin_mut().Shape());
198
199 let is_solid = true;
200 let mut threading_loft = BRepOffsetAPI_ThruSections_ctor(is_solid);
201 threading_loft.pin_mut().AddWire(threading_wire_1.pin_mut().Wire());
202 threading_loft.pin_mut().AddWire(threading_wire_2.pin_mut().Wire());
203 threading_loft.pin_mut().CheckCompatibility(false);
204
205 let threading_shape = threading_loft.pin_mut().Shape();
206
207 let mut compound = TopoDS_Compound_ctor();
209 let builder = BRep_Builder_ctor();
210 let builder = BRep_Builder_upcast_to_topods_builder(&builder);
211 builder.MakeCompound(compound.pin_mut());
212
213 let mut compound_shape = TopoDS_Compound_as_shape(compound);
214 builder.Add(compound_shape.pin_mut(), body_shape);
215 builder.Add(compound_shape.pin_mut(), threading_shape);
216
217 let final_shape = compound_shape;
218
219 let mut stl_writer = StlAPI_Writer_ctor();
221 let triangulation = BRepMesh_IncrementalMesh_ctor(&final_shape, 0.01);
222 let success = write_stl(stl_writer.pin_mut(), triangulation.Shape(), "bottle.stl".to_owned());
223
224 println!("Done! Success = {success}");
225}