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