0027448: BOPTools_AlgoTools::IsMicroEdge does not correspond to shape validity criteria
[occt.git] / src / BRepTest / BRepTest_Fillet2DCommands.cxx
CommitLineData
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
49static 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
185static 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
194static 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
209static 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
237static 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
259static 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
358static 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
435void 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}