b311480e |
1 | // Created by: Joelle CHAUVET |
2 | // Copyright (c) 1996-1999 Matra Datavision |
973c2be1 |
3 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
7fd59977 |
16 | // Modified: Tue Oct 15 10:12:02 1996 |
7fd59977 |
17 | // Add ChFi2d_TangencyError (PRO3529) |
18 | // Modified: Fri Sep 25 09:38:04 1998 |
7fd59977 |
19 | // status = ChFi2d_NotAuthorized if edges are not |
20 | // lines or circles (BUC60288) + partial_result |
21 | |
22 | |
23 | #include <TColgp_Array1OfPnt2d.hxx> |
24 | #include <BRepTest.hxx> |
25 | #include <DBRep.hxx> |
26 | #include <Draw_Interpretor.hxx> |
27 | #include <Draw_Appli.hxx> |
28 | #include <BRepFilletAPI_MakeFillet2d.hxx> |
29 | #include <TopAbs_ShapeEnum.hxx> |
30 | #include <TopoDS_Shape.hxx> |
31 | #include <TopoDS_Edge.hxx> |
32 | #include <TopoDS_Vertex.hxx> |
8b7c5e47 |
33 | #include <TopExp_Explorer.hxx> |
7fd59977 |
34 | #include <TopExp.hxx> |
8b7c5e47 |
35 | #include <TopoDS.hxx> |
36 | |
37 | #include <ChFi2d_FilletAPI.hxx> |
38 | #include <ChFi2d_ChamferAPI.hxx> |
39 | |
40 | #include <BRepBuilderAPI_MakeWire.hxx> |
41 | #include <BRepBuilderAPI_FindPlane.hxx> |
42 | #include <BRep_Builder.hxx> |
7fd59977 |
43 | |
44 | //======================================================================= |
45 | //function : chfi2d |
46 | //purpose : 2d fillets and chamfers |
47 | //======================================================================= |
48 | |
49 | static Standard_Integer chfi2d(Draw_Interpretor& di, Standard_Integer n, const char** a) |
50 | { |
51 | if (n < 3) { |
52 | di << "chfi2d : not enough args"; |
53 | return 1; |
54 | } |
55 | |
56 | // set up the algorithm |
57 | TopoDS_Shape F = DBRep::Get(a[2],TopAbs_FACE); |
58 | if (F.IsNull()) { |
59 | di << "chfi2d : "<< a[2] << " not a face"; |
60 | return 1; |
61 | } |
62 | |
63 | BRepFilletAPI_MakeFillet2d MF(TopoDS::Face(F)); |
64 | if (MF.Status() == ChFi2d_NotPlanar) { |
65 | di << "chfi2d : not a planar face"; |
66 | return 1; |
67 | } |
68 | |
69 | TopoDS_Shape res; |
70 | Standard_Boolean partial_result = Standard_False; |
71 | Standard_Integer i = 3; |
72 | while (i+1 < n) { |
73 | |
74 | TopoDS_Shape aLocalEdge(DBRep::Get(a[i],TopAbs_EDGE)); |
75 | TopoDS_Edge E1 = TopoDS::Edge(aLocalEdge); |
76 | aLocalEdge = DBRep::Get(a[i+1],TopAbs_EDGE); |
77 | TopoDS_Edge E2 = TopoDS::Edge(aLocalEdge); |
78 | // TopoDS_Edge E1 = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE)); |
79 | // TopoDS_Edge E2 = TopoDS::Edge(DBRep::Get(a[i+1],TopAbs_EDGE)); |
80 | |
81 | if (E1.IsNull() || E2.IsNull()) { |
82 | di << "chfi2d : " << a[i] << " or " << a[i+1] << " not an edge"; |
83 | if (partial_result) { |
84 | di <<" WARNING : this is a partial result "; |
85 | DBRep::Set(a[1],res); |
86 | } |
87 | return 1; |
88 | } |
89 | |
90 | TopoDS_Vertex V; |
91 | if (!TopExp::CommonVertex(E1,E2,V)) { |
92 | di << "chfi2d " << a[i] << " and " << a[i+1] << " does not share a vertex"; |
93 | if (partial_result) { |
94 | di <<" WARNING : this is a partial result "; |
95 | DBRep::Set(a[1],res); |
96 | } |
97 | return 1; |
98 | } |
99 | |
100 | i += 2; |
101 | if (i+1 >= n) { |
102 | di << "chfi2d : not enough args"; |
103 | if (partial_result) { |
104 | di <<" WARNING : this is a partial result "; |
105 | DBRep::Set(a[1],res); |
106 | } |
107 | return 1; |
108 | } |
109 | |
91322f44 |
110 | Standard_Real p1 = Draw::Atof(a[i+1]); |
7fd59977 |
111 | if (*a[i] == 'F') { |
112 | MF.AddFillet(V,p1); |
113 | } |
114 | else { |
115 | if (i+2 >= n) { |
116 | di << "chfi2d : not enough args"; |
117 | if (partial_result) { |
118 | di <<" WARNING : this is a partial result "; |
119 | DBRep::Set(a[1],res); |
120 | } |
121 | return 1; |
122 | } |
91322f44 |
123 | Standard_Real p2 = Draw::Atof(a[i+2]); |
7fd59977 |
124 | if (a[i][2] == 'D') { |
125 | MF.AddChamfer(E1,E2,p1,p2); |
126 | } |
127 | else { |
c6541a0c |
128 | MF.AddChamfer(E1,V,p1,p2 * (M_PI / 180.0)); |
7fd59977 |
129 | } |
130 | } |
131 | |
132 | if (MF.Status() == ChFi2d_TangencyError) { |
133 | di << "chfi2d : " << a[i-2] << " and " << a[i-1] << " are tangent "; |
134 | if (partial_result) { |
135 | di <<" WARNING : this is a partial result "; |
136 | DBRep::Set(a[1],res); |
137 | } |
138 | return 1; |
139 | } |
140 | |
141 | if (MF.Status() == ChFi2d_NotAuthorized) { |
142 | di << "chfi2d : " << a[i-2] << " or " << a[i-1] << " is not a line or a circle "; |
143 | if (partial_result) { |
144 | di <<" WARNING : this is a partial result "; |
145 | DBRep::Set(a[1],res); |
146 | } |
147 | return 1; |
148 | } |
149 | |
150 | if (MF.Status() != ChFi2d_IsDone) { |
151 | di << "chfi2d : operation failed on " << a[i-2]; |
152 | if (partial_result) { |
153 | di <<" WARNING : this is a partial result "; |
154 | DBRep::Set(a[1],res); |
155 | } |
156 | return 1; |
157 | } |
158 | else { |
159 | partial_result = Standard_True; |
160 | MF.Build(); |
161 | res = MF.Shape(); |
162 | } |
163 | |
164 | if (*a[i] == 'F') { |
165 | i +=2; |
166 | } |
167 | else { |
168 | i +=3; |
169 | } |
170 | } |
171 | |
172 | MF.Build(); |
173 | DBRep::Set(a[1],MF); |
174 | |
175 | return 0; |
176 | } |
177 | |
8b7c5e47 |
178 | //======================================================================= |
179 | //function : fillet2d |
180 | //purpose : A method to find a plane for 2 edges. |
181 | // : It may return a NULL object of the plane is not found |
182 | // : (the edge are located not in a plane). |
183 | //======================================================================= |
184 | |
185 | static Handle(Geom_Plane) findPlane(const TopoDS_Shape& S) |
186 | { |
187 | Handle(Geom_Plane) plane; |
188 | BRepBuilderAPI_FindPlane planeFinder(S); |
189 | if (planeFinder.Found()) |
190 | plane = planeFinder.Plane(); |
191 | return plane; |
192 | } |
193 | |
194 | static Handle(Geom_Plane) findPlane(const TopoDS_Shape& E1, const TopoDS_Shape& E2) |
195 | { |
196 | BRep_Builder B; |
197 | TopoDS_Compound C; |
198 | B.MakeCompound(C); |
199 | B.Add(C, E1); |
200 | B.Add(C, E2); |
201 | return findPlane(C); |
202 | } |
203 | |
204 | //======================================================================= |
205 | //function : findCommonPoint |
206 | //purpose : Find a common (or the most close) point of two edges. |
207 | //======================================================================= |
208 | |
209 | static gp_Pnt findCommonPoint(const TopoDS_Shape& E1, const TopoDS_Shape& E2) |
210 | { |
211 | TopoDS_Vertex v11, v12, v21, v22; |
212 | TopExp::Vertices(TopoDS::Edge(E1), v11, v12); |
213 | TopExp::Vertices(TopoDS::Edge(E2), v21, v22); |
214 | |
215 | gp_Pnt p11 = BRep_Tool::Pnt(v11); |
216 | gp_Pnt p12 = BRep_Tool::Pnt(v12); |
217 | gp_Pnt p21 = BRep_Tool::Pnt(v21); |
218 | gp_Pnt p22 = BRep_Tool::Pnt(v22); |
219 | |
220 | gp_Pnt common; |
221 | const double d1121 = p11.SquareDistance(p21); |
222 | const double d1122 = p11.SquareDistance(p22); |
223 | const double d1221 = p12.SquareDistance(p21); |
224 | const double d1222 = p12.SquareDistance(p22); |
225 | if (d1121 < d1122 && d1121 < d1221 && d1121 < d1222) |
226 | common = p11; |
227 | else if (d1122 < d1121 && d1122 < d1221 && d1122 < d1222) |
228 | common = p11; |
229 | else if (d1221 < d1121 && d1221 < d1122 && d1221 < d1222) |
230 | common = p12; |
231 | else if (d1222 < d1121 && d1222 < d1122 && d1222 < d1221) |
232 | common = p12; |
233 | |
234 | return common; |
235 | } |
236 | |
237 | static gp_Pnt findCommonPoint(const TopoDS_Shape& W) |
238 | { |
239 | // The common point for two edges inside a wire |
240 | // is a sharing vertex of two edges. |
241 | TopTools_MapOfShape vertices; |
242 | TopExp_Explorer expl(W, TopAbs_VERTEX); |
243 | for (; expl.More(); expl.Next()) |
244 | { |
245 | if (!vertices.Add(expl.Current())) |
246 | { |
247 | return BRep_Tool::Pnt(TopoDS::Vertex(expl.Current())); |
248 | } |
249 | } |
250 | return gp::Origin(); // not found |
251 | } |
252 | |
253 | //======================================================================= |
254 | //function : fillet2d |
255 | //purpose : Fillet 2d based on Newton method (recursive, iteration) |
256 | //usage : fillet2d result wire (or edge1 edge2) radius |
257 | //======================================================================= |
258 | |
259 | static Standard_Integer fillet2d(Draw_Interpretor& di, Standard_Integer n, const char** a) |
260 | { |
261 | if (n != 4 && n != 5) |
262 | { |
263 | di << "Usage : fillet2d result wire (or edge1 edge2) radius"; |
264 | return 1; |
265 | } |
266 | |
267 | TopoDS_Shape E1, E2, W; |
268 | if (n == 5) |
269 | { |
270 | // Get the edges. |
271 | E1 = DBRep::Get(a[2], TopAbs_EDGE, Standard_True); |
272 | E2 = DBRep::Get(a[3], TopAbs_EDGE, Standard_True); |
273 | } |
274 | else |
275 | { |
276 | // Get the wire. |
277 | W = DBRep::Get(a[2], TopAbs_WIRE, Standard_True); |
278 | } |
279 | |
280 | // Get the radius value. |
281 | const Standard_Real radius = Atof(n == 5 ? a[4] : a[3]); |
282 | |
283 | // Find plane of the edges. |
284 | Handle(Geom_Plane) hPlane = n == 5 ? findPlane(E1, E2) : findPlane(W); |
285 | if (hPlane.IsNull()) |
286 | { |
287 | di << "Error: the edges are located not in a plane."; |
288 | return 1; |
289 | } |
290 | |
291 | // Algo. |
292 | ChFi2d_FilletAPI algo; |
293 | gp_Pln plane = hPlane->Pln(); |
294 | if (n == 5) |
295 | { |
296 | const TopoDS_Edge& e1 = TopoDS::Edge(E1); |
297 | const TopoDS_Edge& e2 = TopoDS::Edge(E2); |
298 | algo.Init(e1, e2, plane); |
299 | } |
300 | else |
301 | { |
302 | const TopoDS_Wire& w = TopoDS::Wire(W); |
303 | algo.Init(w, plane); |
304 | } |
305 | Standard_Boolean status = algo.Perform(radius); |
306 | if (!status) |
307 | { |
308 | di << "Error: the algrithm failed."; |
309 | return 1; |
310 | } |
311 | |
312 | // Find a common point of the edges. |
313 | gp_Pnt common = n == 5 ? findCommonPoint(E1, E2) : findCommonPoint(W); |
314 | |
315 | // Get the number of solutions (usually it is equal to 1). |
316 | Standard_Integer nbSolutions = algo.NbResults(common); |
317 | if (!nbSolutions) |
318 | { |
319 | di << "Error: no solutions."; |
320 | return 1; |
321 | } |
322 | |
323 | // Get the result for the "nearest" solution (near the common point). |
324 | TopoDS_Edge M1, M2; // modified E1 and E2 |
325 | TopoDS_Edge fillet = algo.Result(common, M1, M2); |
326 | if (fillet.IsNull()) |
327 | { |
328 | di << "Error: the algrithm produced no result."; |
329 | return 1; |
330 | } |
331 | |
332 | // Set result for DRAW. |
333 | DBRep::Set(a[1], fillet); |
334 | |
335 | // Update neighbour edges in DRAW. |
336 | if (n == 5) |
337 | { |
338 | DBRep::Set(a[2], M1); |
339 | DBRep::Set(a[3], M2); |
340 | } |
341 | else // recreate the wire using the fillet |
342 | { |
343 | BRepBuilderAPI_MakeWire mkWire(M1, fillet, M2); |
344 | if (mkWire.IsDone()) |
345 | DBRep::Set(a[1], mkWire.Wire()); |
346 | else |
347 | DBRep::Set(a[1], fillet); |
348 | } |
349 | return 0; |
350 | } |
351 | |
352 | //======================================================================= |
353 | //function : chamfer2d |
354 | //purpose : Chamfer 2d. |
355 | //usage : chamfer2d result wire (or edge1 edge2) length1 length2 |
356 | //======================================================================= |
357 | |
358 | static Standard_Integer chamfer2d(Draw_Interpretor& di, Standard_Integer n, const char** a) |
359 | { |
360 | if (n != 5 && n != 6) |
361 | { |
362 | di << "Usage : chamfer2d result wire (or edge1 edge2) length1 length2"; |
363 | return 1; |
364 | } |
365 | |
366 | TopoDS_Shape W; |
367 | TopoDS_Shape E1, E2; |
368 | if (n == 6) |
369 | { |
370 | // Get the edges. |
371 | E1 = DBRep::Get(a[2], TopAbs_EDGE, Standard_True); |
372 | E2 = DBRep::Get(a[3], TopAbs_EDGE, Standard_True); |
373 | } |
374 | else |
375 | { |
376 | W = DBRep::Get(a[2], TopAbs_WIRE, Standard_True); |
377 | } |
378 | |
379 | // Get the lengths. |
380 | const Standard_Real length1 = (n == 6) ? Atof(a[4]) : Atof(a[3]); |
381 | const Standard_Real length2 = (n == 6) ? Atof(a[5]) : Atof(a[4]); |
382 | |
383 | // Algo. |
384 | ChFi2d_ChamferAPI algo; |
385 | if (n == 6) |
386 | { |
387 | const TopoDS_Edge& e1 = TopoDS::Edge(E1); |
388 | const TopoDS_Edge& e2 = TopoDS::Edge(E2); |
389 | algo.Init(e1, e2); |
390 | } |
391 | else |
392 | { |
393 | const TopoDS_Wire& w = TopoDS::Wire(W); |
394 | algo.Init(w); |
395 | } |
396 | |
397 | // Prepare the chamfer. |
398 | algo.Perform(); |
399 | |
400 | // Get the result. |
401 | TopoDS_Edge M1, M2; // modified E1 and E2 |
402 | TopoDS_Edge chamfer = algo.Result(M1, M2, length1, length2); |
403 | if (chamfer.IsNull()) |
404 | { |
405 | di << "Error: the algrithm produced no result."; |
406 | return 1; |
407 | } |
408 | |
409 | if (n == 6) |
410 | { |
411 | // Set result for DRAW. |
412 | DBRep::Set(a[1], chamfer); |
413 | |
414 | // Update neighbour edges in DRAW. |
415 | DBRep::Set(a[2], M1); |
416 | DBRep::Set(a[3], M2); |
417 | } |
418 | else // recreate the wire using the chamfer |
419 | { |
420 | BRepBuilderAPI_MakeWire mkWire(M1, chamfer, M2); |
421 | if (mkWire.IsDone()) |
422 | DBRep::Set(a[1], mkWire.Wire()); |
423 | else |
424 | DBRep::Set(a[1], chamfer); |
425 | } |
426 | |
427 | return 0; |
428 | } |
429 | |
7fd59977 |
430 | //======================================================================= |
431 | //function : Fillet2DCommands |
432 | //purpose : |
433 | //======================================================================= |
434 | |
435 | void BRepTest::Fillet2DCommands(Draw_Interpretor& theCommands) |
436 | { |
437 | static Standard_Boolean done = Standard_False; |
438 | if (done) return; |
439 | done = Standard_True; |
440 | |
441 | DBRep::BasicCommands(theCommands); |
442 | |
443 | const char* g = "TOPOLOGY Fillet2D construction commands"; |
444 | |
445 | theCommands.Add("chfi2d","chfi2d result face [edge1 edge2 (F radius/CDD d1 d2/CDA d ang) ....]",__FILE__,chfi2d,g); |
8b7c5e47 |
446 | theCommands.Add("fillet2d","fillet2d result wire (or edge1 edge2) radius",__FILE__,fillet2d,g); |
447 | theCommands.Add("chamfer2d","chamfer2d result wire (or edge1 edge2) length1 length2",__FILE__,chamfer2d,g); |
7fd59977 |
448 | } |